Use new argument parser API

This commit is contained in:
Martchus 2016-06-14 00:52:33 +02:00
parent f6e9368792
commit 72621f7ad8
4 changed files with 149 additions and 133 deletions

View File

@ -6,7 +6,7 @@ set(META_APP_NAME "Tag Editor")
set(META_APP_CATEGORIES "Utility;Audio;Video;")
set(META_APP_AUTHOR "Martchus")
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
set(META_APP_DESCRIPTION "A tageditor with Qt GUI and command line interface. Supports MP4 (iTunes), ID3, Vorbis, Opus and Matroska.")
set(META_APP_DESCRIPTION "A tageditor with Qt GUI and command line interface. Supports MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska.")
set(META_VERSION_MAJOR 1)
set(META_VERSION_MINOR 4)
set(META_VERSION_PATCH 1)
@ -130,6 +130,10 @@ set(ICON_FILES
resources/icons/hicolor/scalable/apps/${META_PROJECT_NAME}.svg
)
set(DOC_FILES
README.md
)
# find c++utilities
find_package(c++utilities 3.3.0 REQUIRED)
use_cpp_utilities()

View File

@ -30,26 +30,29 @@ namespace Cli {
SetTagInfoArgs::SetTagInfoArgs(Argument &filesArg, Argument &verboseArg) :
filesArg(filesArg),
verboseArg(verboseArg),
docTitleArg("doc-title", "d", "specifies the document title (has no affect if not supported by the container)"),
removeOtherFieldsArg("remove-other-fields", nullptr, "if present ALL unspecified tag fields will be removed (to remove a specific field use eg. \"album=\")"),
treatUnknownFilesAsMp3FilesArg("treat-unknown-as-mp3", nullptr, "if present unknown files will be treatet as MP3 files"),
id3v1UsageArg("id3v1-usage", nullptr, "specifies the ID3v1 usage (only used when already present by default); only relevant when dealing with MP3 files (or files treated as such)"),
id3v2UsageArg("id3v2-usage", nullptr, "specifies the ID3v2 usage (always used by default); only relevant when dealing with MP3 files (or files treated as such)"),
mergeMultipleSuccessiveTagsArg("merge-successive-tags", nullptr, "if present multiple successive ID3v2 tags will be merged"),
id3v2VersionArg("id3v2-version", nullptr, "forces a specific ID3v2 version to be used; only relevant when ID3v2 is used"),
encodingArg("encoding", nullptr, "specifies the preferred encoding"),
removeTargetsArg("remove-targets", nullptr, "removes all tags with the specified targets (which must be separated by \",\")"),
attachmentsArg("attachments", nullptr, "specifies attachments to be added/updated/removed (multiple attachments must be separated by \",\""),
removeExistingAttachmentsArg("remove-existing-attachments", "ra", "specifies names/IDs of existing attachments to be removed"),
minPaddingArg("min-padding", nullptr, "specifies the minimum padding before the media data"),
maxPaddingArg("max-padding", nullptr, "specifies the maximum padding before the media data"),
prefPaddingArg("preferred-padding", nullptr, "specifies the preferred padding before the media data"),
tagPosArg("tag-pos", nullptr, "specifies the preferred tag position"),
forceTagPosArg("force-tag-pos", nullptr, "forces the specified tag postion to be used even if it requires the file to be rewritten"),
indexPosArg("index-pos", nullptr, "specifies the preferred index position"),
forceIndexPosArg("force-index-pos", nullptr, "forces the specified index postion to be used even if it requires the file to be rewritten"),
forceRewriteArg("force-rewrite", nullptr, "forces the file to rewritten from the scratch"),
setTagInfoArg("set-tag-info", "set", "sets the values of all specified tag fields")
docTitleArg("doc-title", 'd', "specifies the document title (has no affect if not supported by the container)"),
removeOtherFieldsArg("remove-other-fields", '\0', "if present ALL unspecified tag fields will be removed (to remove a specific field use eg. \"album=\")"),
treatUnknownFilesAsMp3FilesArg("treat-unknown-as-mp3", '\0', "if present unknown files will be treatet as MP3 files"),
id3v1UsageArg("id3v1-usage", '\0', "specifies the ID3v1 usage (only used when already present by default); only relevant when dealing with MP3 files (or files treated as such)"),
id3v2UsageArg("id3v2-usage", '\0', "specifies the ID3v2 usage (always used by default); only relevant when dealing with MP3 files (or files treated as such)"),
mergeMultipleSuccessiveTagsArg("merge-successive-tags", '\0', "if present multiple successive ID3v2 tags will be merged"),
id3v2VersionArg("id3v2-version", '\0', "forces a specific ID3v2 version to be used; only relevant when ID3v2 is used"),
encodingArg("encoding", '\0', "specifies the preferred encoding"),
removeTargetsArg("remove-targets", '\0', "removes all tags with the specified targets (which must be separated by \",\")"),
attachmentsArg("attachments", '\0', "specifies attachments to be added/updated/removed (multiple attachments must be separated by \",\""),
removeExistingAttachmentsArg("remove-existing-attachments", 'r', "specifies names/IDs of existing attachments to be removed"),
minPaddingArg("min-padding", '\0', "specifies the minimum padding before the media data"),
maxPaddingArg("max-padding", '\0', "specifies the maximum padding before the media data"),
prefPaddingArg("preferred-padding", '\0', "specifies the preferred padding before the media data"),
tagPosValueArg("value", 'v', "specifies the position, either front, back or current"),
forceTagPosArg("force", 'f', "forces the specified position even if the file to be rewritten"),
tagPosArg("tag-pos", '\0', "specifies the preferred tag position"),
indexPosValueArg("value", 'v', "specifies the position, either front, back or current"),
forceIndexPosArg("force", 'f', "forces the specified position even if the file to be rewritten"),
indexPosArg("index-pos", '\0', "specifies the preferred index position"),
forceRewriteArg("force-rewrite", '\0', "forces the file to rewritten from the scratch"),
valuesArg("fields", 'n', "specifies the values to be set"),
setTagInfoArg("set", 's', "sets the values of all specified tag fields")
{
docTitleArg.setCombinable(true);
docTitleArg.setRequiredValueCount(-1);
@ -85,20 +88,23 @@ SetTagInfoArgs::SetTagInfoArgs(Argument &filesArg, Argument &verboseArg) :
prefPaddingArg.setRequiredValueCount(1);
prefPaddingArg.setValueNames({"preferred padding in byte"});
prefPaddingArg.setCombinable(true);
tagPosArg.setRequiredValueCount(1);
tagPosValueArg.setRequiredValueCount(1);
forceTagPosArg.setCombinable(true);
tagPosArg.setValueNames({"front/back/current"});
tagPosArg.setCombinable(true);
tagPosArg.setSecondaryArguments({&forceTagPosArg});
indexPosArg.setRequiredValueCount(1);
tagPosArg.setSubArguments({&tagPosValueArg, &forceTagPosArg});
indexPosValueArg.setRequiredValueCount(1);
forceIndexPosArg.setCombinable(true);
indexPosArg.setValueNames({"front/back/current"});
indexPosArg.setCombinable(true);
indexPosArg.setSecondaryArguments({&forceIndexPosArg});
indexPosArg.setSubArguments({&indexPosValueArg, &forceIndexPosArg});
forceRewriteArg.setCombinable(true);
valuesArg.setValueNames({"title=foo", "album=bar", "cover=/path/to/file"});
valuesArg.setRequiredValueCount(-1);
valuesArg.setImplicit(true);
setTagInfoArg.setDenotesOperation(true);
setTagInfoArg.setCallback(std::bind(Cli::setTagInfo, _1, std::cref(*this)));
setTagInfoArg.setRequiredValueCount(-1);
setTagInfoArg.setValueNames({"title=foo", "album=bar", "cover=/path/to/file"});
setTagInfoArg.setSecondaryArguments({&filesArg, &docTitleArg, &removeOtherFieldsArg, &treatUnknownFilesAsMp3FilesArg, &id3v1UsageArg, &id3v2UsageArg,
setTagInfoArg.setSubArguments({&valuesArg, &filesArg, &docTitleArg, &removeOtherFieldsArg, &treatUnknownFilesAsMp3FilesArg, &id3v1UsageArg, &id3v2UsageArg,
&mergeMultipleSuccessiveTagsArg, &id3v2VersionArg, &encodingArg, &removeTargetsArg, &attachmentsArg,
&removeExistingAttachmentsArg, &minPaddingArg, &maxPaddingArg, &prefPaddingArg, &tagPosArg,
&indexPosArg, &forceRewriteArg, &verboseArg});
@ -114,86 +120,92 @@ int main(int argc, char *argv[])
QT_CONFIG_ARGUMENTS qtConfigArgs;
HelpArgument helpArg(parser);
// verbose option
Argument verboseArg("verbose", "v", "be verbose");
Argument verboseArg("verbose", 'v', "be verbose");
verboseArg.setCombinable(true);
// recursive option
Argument recursiveArg("recursive", "r", "includes subdirectories");
Argument recursiveArg("recursive", 'r', "includes subdirectories");
// input/output file/files
Argument filesArg("files", "f", "specifies the path of the file(s) to be opened");
filesArg.setValueNames({"path 1", "path 2"});
filesArg.setRequiredValueCount(-1);
filesArg.setRequired(false);
filesArg.setImplicit(true);
qtConfigArgs.qtWidgetsGuiArg().addSecondaryArgument(&filesArg);
Argument fileArg("file", "if", "specifies the path of the input file");
Argument fileArg("file", 'f', "specifies the path of the file to be opened");
fileArg.setValueNames({"path"});
fileArg.setRequiredValueCount(1);
fileArg.setRequired(true);
Argument outputFileArg("output-file", "of", "specifies the path of the output file");
fileArg.setCombinable(true);
Argument defaultFileArg(fileArg);
defaultFileArg.setImplicit(true);
Argument filesArg("files", 'f', "specifies the path of the file(s) to be opened");
filesArg.setValueNames({"path 1", "path 2"});
filesArg.setRequiredValueCount(-1);
filesArg.setCombinable(true);
Argument outputFileArg("output-file", 'o', "specifies the path of the output file");
outputFileArg.setValueNames({"path"});
outputFileArg.setRequiredValueCount(1);
outputFileArg.setRequired(true);
outputFileArg.setCombinable(true);
// print field names
Argument printFieldNamesArg("print-field-names", nullptr, "prints available field names");
Argument printFieldNamesArg("print-field-names", '\0', "prints available field names");
printFieldNamesArg.setCallback(Cli::printFieldNames);
// display general file info
Argument displayFileInfoArg("display-file-info", "info", "displays general file information");
Argument displayFileInfoArg("display-file-info", 'i', "displays general file information");
displayFileInfoArg.setDenotesOperation(true);
displayFileInfoArg.setCallback(std::bind(Cli::displayFileInfo, _1, std::cref(filesArg), std::cref(verboseArg)));
displayFileInfoArg.setSecondaryArguments({&filesArg, &verboseArg});
displayFileInfoArg.setSubArguments({&filesArg, &verboseArg});
// display tag info
Argument displayTagInfoArg("display-tag-info", "get", "displays the values of all specified tag fields (displays all fields if none specified)");
Argument fieldsArg("fields", 'n', "specifies the field names to be displayed");
fieldsArg.setValueNames({"title", "album", "artist", "trackpos"});
fieldsArg.setRequiredValueCount(-1);
fieldsArg.setImplicit(true);
Argument displayTagInfoArg("get", 'g', "displays the values of all specified tag fields (displays all fields if none specified)");
displayTagInfoArg.setDenotesOperation(true);
displayTagInfoArg.setCallback(std::bind(Cli::displayTagInfo, _1, std::cref(filesArg), std::cref(verboseArg)));
displayTagInfoArg.setRequiredValueCount(-1);
displayTagInfoArg.setValueNames({"title", "album", "artist", "trackpos"});
displayTagInfoArg.setSecondaryArguments({&filesArg, &verboseArg});
displayTagInfoArg.setSubArguments({&fieldsArg, &filesArg, &verboseArg});
// set tag info
Cli::SetTagInfoArgs setTagInfoArgs(filesArg, verboseArg);
// extract cover
Argument extractFieldArg("extract", "ext", "extracts the specified field from the specified file");
extractFieldArg.setRequiredValueCount(1);
extractFieldArg.setValueNames({"field"});
extractFieldArg.setSecondaryArguments({&fileArg, &outputFileArg, &verboseArg});
Argument fieldArg("fields", 'n', "specifies the field to be extracted");
fieldArg.setValueNames({"field name"});
fieldArg.setRequiredValueCount(1);
fieldArg.setImplicit(true);
Argument extractFieldArg("extract", 'e', "extracts the specified field from the specified file");
extractFieldArg.setSubArguments({&fieldArg, &fileArg, &outputFileArg, &verboseArg});
extractFieldArg.setDenotesOperation(true);
extractFieldArg.setCallback(std::bind(Cli::extractField, _1, std::cref(fileArg), std::cref(outputFileArg), std::cref(verboseArg)));
// file info
Argument validateArg("validate", "c", "validates the file integrity as accurately as possible; the structure of the file will be parsed completely");
validateArg.setDenotesOperation(true);
Argument validateArg("validate", 'c', "validates the file integrity as accurately as possible; the structure of the file will be parsed completely");
validateArg.setCombinable(true);
Argument genInfoArg("html-info", nullptr, "generates technical information about the specified file as HTML document");
Argument genInfoArg("html-info", '\0', "generates technical information about the specified file as HTML document");
genInfoArg.setDenotesOperation(true);
genInfoArg.setSecondaryArguments({&fileArg, &validateArg, &outputFileArg});
genInfoArg.setSubArguments({&fileArg, &validateArg, &outputFileArg});
genInfoArg.setCallback(std::bind(Cli::generateFileInfo, _1, std::cref(fileArg), std::cref(outputFileArg), std::cref(validateArg)));
// remove backup files
Argument remBackupFilesArg("remove-backup-files", nullptr, "removes all files with \".bak\" suffix in the given directory and in subdirectories if recursive option is present");
Argument directoryArg("directory", 'd', "specifies the directory");
directoryArg.setRequiredValueCount(1);
directoryArg.setValueNames({"path"});
directoryArg.setImplicit(true);
Argument remBackupFilesArg("remove-backup-files", '\0', "removes all files with \".bak\" suffix in the given directory and in subdirectories if recursive option is present");
remBackupFilesArg.setDenotesOperation(true);
remBackupFilesArg.setCallback(std::bind(Cli::removeBackupFiles, _1, std::cref(recursiveArg)));
remBackupFilesArg.setValueNames({"directory"});
remBackupFilesArg.setRequiredValueCount(1);
remBackupFilesArg.setSecondaryArguments({&recursiveArg});
remBackupFilesArg.setSubArguments({&directoryArg, &recursiveArg});
// renaming utility
Argument renamingUtilityArg("renaming-utility", nullptr, "launches the renaming utility instead of the main GUI");
Argument renamingUtilityArg("renaming-utility", '\0', "launches the renaming utility instead of the main GUI");
renamingUtilityArg.setCombinable(true);
// set arguments to parser
qtConfigArgs.qtWidgetsGuiArg().addSecondaryArgument(&filesArg);
qtConfigArgs.qtWidgetsGuiArg().addSecondaryArgument(&renamingUtilityArg);
parser.setMainArguments({&printFieldNamesArg, &displayFileInfoArg, &displayTagInfoArg, &setTagInfoArgs.setTagInfoArg, &extractFieldArg, &genInfoArg, &remBackupFilesArg, &qtConfigArgs.qtWidgetsGuiArg(), &helpArg});
qtConfigArgs.qtWidgetsGuiArg().setAbbreviation('\0');
qtConfigArgs.qtWidgetsGuiArg().addSubArgument(&defaultFileArg);
qtConfigArgs.qtWidgetsGuiArg().addSubArgument(&renamingUtilityArg);
parser.setMainArguments({&qtConfigArgs.qtWidgetsGuiArg(), &printFieldNamesArg, &displayFileInfoArg, &displayTagInfoArg, &setTagInfoArgs.setTagInfoArg, &extractFieldArg, &genInfoArg, &remBackupFilesArg, &helpArg});
// parse given arguments
try {
parser.parseArgs(argc, argv);
if(qtConfigArgs.areQtGuiArgsPresent()) {
#ifdef GUI_QTWIDGETS
return QtGui::runWidgetsGui(argc, argv, qtConfigArgs, filesArg.values().empty() ? QString() : QString::fromLocal8Bit(filesArg.values().front().data()), renamingUtilityArg.isPresent());
return QtGui::runWidgetsGui(argc, argv, qtConfigArgs, defaultFileArg.isPresent() && !defaultFileArg.values().empty() ? QString::fromLocal8Bit(defaultFileArg.values().front()) : QString(), renamingUtilityArg.isPresent());
#else
CMD_UTILS_START_CONSOLE;
cout << "Application has not been build with Qt widgets GUI support." << endl;
cerr << "Application has not been build with Qt widgets GUI support." << endl;
#endif
}
} catch(const Failure &ex) {
CMD_UTILS_START_CONSOLE;
cout << "Unable to parse arguments. " << ex.what() << "\nSee --help for available commands." << endl;
cerr << "Unable to parse arguments. " << ex.what() << "\nSee --help for available commands." << endl;
}
return 0;
}

View File

@ -151,7 +151,7 @@ void printNotifications(const MediaFileInfo &fileInfo, const char *head = nullpt
printNotifications(notifications, head, beVerbose);
}
void printFieldNames(const StringVector &parameterValues)
void printFieldNames(const std::vector<const char *> &parameterValues)
{
CMD_UTILS_START_CONSOLE;
VAR_UNUSED(parameterValues)
@ -160,7 +160,7 @@ void printFieldNames(const StringVector &parameterValues)
"recordlabel cover composer rating description" << endl;
}
void removeBackupFiles(const StringVector &parameterValues, const Argument &recursiveArg)
void removeBackupFiles(const std::vector<const char *> &parameterValues, const Argument &recursiveArg)
{
CMD_UTILS_START_CONSOLE;
QDir dir(QString::fromStdString(parameterValues.at(0)));
@ -173,11 +173,11 @@ TagUsage parseUsageDenotation(const Argument &usageArg, TagUsage defaultUsage)
{
if(usageArg.isPresent()) {
const auto &val = usageArg.values().front();
if(val == "never") {
if(!strcmp(val, "never")) {
return TagUsage::Never;
} else if(val == "keepexisting") {
} else if(!strcmp(val, "keepexisting")) {
return TagUsage::KeepExisting;
} else if(val == "always") {
} else if(!strcmp(val, "always")) {
return TagUsage::Always;
} else {
cout << "Warning: The specified tag usage \"" << val << "\" is invalid and will be ignored." << endl;
@ -190,15 +190,15 @@ TagTextEncoding parseEncodingDenotation(const Argument &encodingArg, TagTextEnco
{
if(encodingArg.isPresent()) {
const auto &val = encodingArg.values().front();
if(val == "utf8") {
if(!strcmp(val, "utf8")) {
return TagTextEncoding::Utf8;
} else if(val == "latin1") {
} else if(!strcmp(val, "latin1")) {
return TagTextEncoding::Latin1;
} else if(val == "utf16be") {
} else if(!strcmp(val, "utf16be")) {
return TagTextEncoding::Utf16BigEndian;
} else if(val == "utf16le") {
} else if(!strcmp(val, "utf16le")) {
return TagTextEncoding::Utf16LittleEndian;
} else if(val == "auto") {
} else if(!strcmp(val, "auto")) {
} else {
cout << "Warning: The specified encoding \"" << val << "\" is invalid and will be ignored." << endl;
}
@ -210,11 +210,11 @@ ElementPosition parsePositionDenotation(const Argument &posArg, ElementPosition
{
if(posArg.isPresent()) {
const auto &val = posArg.values().front();
if(val == "front") {
if(!strcmp(val, "front")) {
return ElementPosition::BeforeData;
} else if(val == "back") {
} else if(!strcmp(val, "back")) {
return ElementPosition::AfterData;
} else if(val == "keep") {
} else if(!strcmp(val, "keep")) {
return ElementPosition::Keep;
} else {
cout << "Warning: The specified position \"" << val << "\" is invalid and will be ignored." << endl;
@ -227,8 +227,8 @@ uint64 parseUInt64(const Argument &arg, uint64 defaultValue)
{
if(arg.isPresent()) {
try {
if(startsWith<string>(arg.values().front(), "0x")) {
return stringToNumber<decltype(parseUInt64(arg, defaultValue))>(arg.values().front().substr(2), 16);
if(*arg.values().front() == '0' && *(arg.values().front() + 1) == 'x') {
return stringToNumber<decltype(parseUInt64(arg, defaultValue))>(arg.values().front() + 2, 16);
} else {
return stringToNumber<decltype(parseUInt64(arg, defaultValue))>(arg.values().front());
}
@ -284,20 +284,21 @@ bool applyTargetConfiguration(TagTarget &target, const std::string &configStr)
}
}
vector<FieldDenotation> parseFieldDenotations(const StringVector &fieldDenotations, bool readOnly)
vector<FieldDenotation> parseFieldDenotations(const std::vector<const char *> &fieldDenotations, bool readOnly)
{
vector<FieldDenotation> fields;
fields.reserve(fieldDenotations.size());
TagType currentTagType = TagType::Unspecified;
TagTarget currentTagTarget;
for(const string &fieldDenotationString : fieldDenotations) {
for(const char *fieldDenotationString : fieldDenotations) {
// check for tag or target specifier
if(strncmp(fieldDenotationString.c_str(), "tag:", 4) == 0) {
if(fieldDenotationString.size() == 4) {
const auto fieldDenotationLen = strlen(fieldDenotationString);
if(strncmp(fieldDenotationString, "tag:", 4) == 0) {
if(fieldDenotationLen == 4) {
cout << "Warning: The \"tag\"-specifier has been used with no value(s) and hence is ignored. Possible values are: id3,id3v1,id3v2,itunes,vorbis,matroska,all" << endl;
} else {
TagType tagType = TagType::Unspecified;
for(const auto &part : splitString(fieldDenotationString.substr(4), ",", EmptyPartsTreat::Omit)) {
for(const auto &part : splitString(fieldDenotationString + 4, ",", EmptyPartsTreat::Omit)) {
if(part == "id3v1") {
tagType |= TagType::Id3v1Tag;
} else if(part == "id3v2") {
@ -326,8 +327,8 @@ vector<FieldDenotation> parseFieldDenotations(const StringVector &fieldDenotatio
continue;
}
// read field name
auto equationPos = fieldDenotationString.find('=');
auto fieldName = equationPos != string::npos ? fieldDenotationString.substr(0, equationPos) : fieldDenotationString;
const auto equationPos = strchr(fieldDenotationString, '=');
auto fieldName = equationPos ? string(fieldDenotationString, static_cast<size_t>(equationPos - fieldDenotationString)) : fieldDenotationString;
// field name might denote increment ("+") or path disclosure (">")
auto fieldNamePos = fieldName.size();
DenotationType type = DenotationType::Normal;
@ -354,7 +355,7 @@ vector<FieldDenotation> parseFieldDenotations(const StringVector &fieldDenotatio
cout << "Warning: Ignoring field denotation \"" << fieldDenotationString << "\" because no field name has been specified." << endl;
continue;
} else if(++fieldNamePos < fieldName.size()) {
fieldName = fieldName.substr(0, fieldNamePos);
fieldName = string(fieldName, fieldNamePos);
}
// parse the denoted filed
KnownField field;
@ -424,11 +425,11 @@ vector<FieldDenotation> parseFieldDenotations(const StringVector &fieldDenotatio
fieldDenotation.type = type;
fieldDenotation.tagType = currentTagType;
fieldDenotation.tagTarget = currentTagTarget;
if(equationPos != string::npos) {
if(equationPos) {
if(readOnly) {
cout << "Warning: Specified value for \"" << fieldName << "\" will be ignored." << endl;
} else {
fieldDenotation.values.emplace_back(make_pair(mult == 1 ? fieldDenotation.values.size() : fileIndex, QString::fromLocal8Bit(fieldDenotationString.data() + equationPos + 1)));
fieldDenotation.values.emplace_back(make_pair(mult == 1 ? fieldDenotation.values.size() : fileIndex, QString::fromLocal8Bit(equationPos + 1)));
}
}
}
@ -569,7 +570,7 @@ bool AttachmentInfo::next(AbstractContainer *container)
return true;
}
void generateFileInfo(const StringVector &parameterValues, const Argument &inputFileArg, const Argument &outputFileArg, const Argument &validateArg)
void generateFileInfo(const std::vector<const char *> &parameterValues, const Argument &inputFileArg, const Argument &outputFileArg, const Argument &validateArg)
{
CMD_UTILS_START_CONSOLE;
VAR_UNUSED(parameterValues)
@ -581,7 +582,7 @@ void generateFileInfo(const StringVector &parameterValues, const Argument &input
inputFileInfo.parseEverything();
cout << "Saving file info of \"" << inputFileArg.values().front() << "\" ..." << endl;
NotificationList origNotify;
QFile file(QString::fromLocal8Bit(outputFileArg.values().front().c_str()));
QFile file(QString::fromLocal8Bit(outputFileArg.values().front()));
if(file.open(QFile::WriteOnly) && file.write(HtmlInfo::generateInfo(inputFileInfo, origNotify)) && file.flush()) {
cout << "File information has been saved to \"" << outputFileArg.values().front() << "\"." << endl;
} else {
@ -639,10 +640,10 @@ void printProperty(const char *propName, const intType value, const char *suffix
}
}
void displayFileInfo(const StringVector &, const Argument &filesArg, const Argument &verboseArg)
void displayFileInfo(const std::vector<const char *> &, const Argument &filesArg, const Argument &verboseArg)
{
CMD_UTILS_START_CONSOLE;
if(!filesArg.valueCount()) {
if(filesArg.values().empty()) {
cout << "Error: No files have been specified." << endl;
return;
}
@ -766,10 +767,10 @@ void displayFileInfo(const StringVector &, const Argument &filesArg, const Argum
}
}
void displayTagInfo(const StringVector &parameterValues, const Argument &filesArg, const Argument &verboseArg)
void displayTagInfo(const std::vector<const char *> &parameterValues, const Argument &filesArg, const Argument &verboseArg)
{
CMD_UTILS_START_CONSOLE;
if(!filesArg.valueCount()) {
if(filesArg.values().empty()) {
cout << "Error: No files have been specified." << endl;
return;
}
@ -864,10 +865,10 @@ void displayTagInfo(const StringVector &parameterValues, const Argument &filesAr
}
}
void setTagInfo(const StringVector &parameterValues, const SetTagInfoArgs &args)
void setTagInfo(const std::vector<const char *> &parameterValues, const SetTagInfoArgs &args)
{
CMD_UTILS_START_CONSOLE;
if(!args.setTagInfoArg.valueCount()) {
if(args.setTagInfoArg.values().empty()) {
cout << "Error: No files have been specified." << endl;
return;
}
@ -888,7 +889,7 @@ void setTagInfo(const StringVector &parameterValues, const SetTagInfoArgs &args)
targetsToRemove.emplace_back();
bool validRemoveTargetsSpecified = false;
for(const auto &targetDenotation : args.removeTargetsArg.values()) {
if(targetDenotation == ",") {
if(!strcmp(targetDenotation, ",")) {
if(validRemoveTargetsSpecified) {
targetsToRemove.emplace_back();
}
@ -906,7 +907,7 @@ void setTagInfo(const StringVector &parameterValues, const SetTagInfoArgs &args)
if(id3v2Version < 1 || id3v2Version > 4) {
throw ConversionException();
}
} catch (ConversionException &) {
} catch (const ConversionException &) {
id3v2Version = 3;
cout << "Warning: The specified ID3v2 version \"" << args.id3v2VersionArg.values().front() << "\" is invalid and will be ingored." << endl;
}
@ -1041,36 +1042,35 @@ void setTagInfo(const StringVector &parameterValues, const SetTagInfoArgs &args)
}
// add/update/remove attachments explicitely
AttachmentInfo currentInfo;
for(const auto &value : args.attachmentsArg.values()) {
const auto *data = value.data();
if(value == ",") {
for(const char *value : args.attachmentsArg.values()) {
if(!strcmp(value, ",")) {
attachmentsModified |= currentInfo.next(container);
} else if(value == "add") {
} else if(!strcmp(value, "add")) {
currentInfo.action = AttachmentAction::Add;
} else if(value == "update-by-id") {
} else if(!strcmp(value, "update-by-id")) {
currentInfo.action = AttachmentAction::UpdateById;
} else if(value == "update-by-name") {
} else if(!strcmp(value, "update-by-name")) {
currentInfo.action = AttachmentAction::UpdateByName;
} else if(value == "remove-by-id") {
} else if(!strcmp(value, "remove-by-id")) {
currentInfo.action = AttachmentAction::RemoveById;
} else if(value == "remove-by-name") {
} else if(!strcmp(value, "remove-by-name")) {
currentInfo.action = AttachmentAction::RemoveByName;
} else if(!strncmp(data, "id=", 3)) {
} else if(!strncmp(value, "id=", 3)) {
try {
currentInfo.id = stringToNumber<uint64, string>(data + 3);
currentInfo.id = stringToNumber<uint64, string>(value + 3);
} catch(const ConversionException &) {
container->addNotification(NotificationType::Warning, "The specified attachment ID \"" + string(data + 3) + "\" is invalid.", context);
container->addNotification(NotificationType::Warning, "The specified attachment ID \"" + string(value + 3) + "\" is invalid.", context);
}
} else if(!strncmp(data, "path=", 5)) {
currentInfo.path = data + 5;
} else if(!strncmp(data, "name=", 5)) {
currentInfo.name = data + 5;
} else if(!strncmp(data, "mime=", 5)) {
currentInfo.mime = data + 5;
} else if(!strncmp(data, "desc=", 5)) {
currentInfo.desc = data + 5;
} else if(!strncmp(value, "path=", 5)) {
currentInfo.path = value + 5;
} else if(!strncmp(value, "name=", 5)) {
currentInfo.name = value + 5;
} else if(!strncmp(value, "mime=", 5)) {
currentInfo.mime = value + 5;
} else if(!strncmp(value, "desc=", 5)) {
currentInfo.desc = value + 5;
} else {
container->addNotification(NotificationType::Warning, "The attachment specification \"" + value + "\" is invalid and will be ignored.", context);
container->addNotification(NotificationType::Warning, "The attachment specification \"" + string(value) + "\" is invalid and will be ignored.", context);
}
}
attachmentsModified |= currentInfo.next(container);
@ -1105,7 +1105,7 @@ void setTagInfo(const StringVector &parameterValues, const SetTagInfoArgs &args)
}
}
void extractField(const StringVector &parameterValues, const Argument &inputFileArg, const Argument &outputFileArg, const Argument &verboseArg)
void extractField(const std::vector<const char *> &parameterValues, const Argument &inputFileArg, const Argument &outputFileArg, const Argument &verboseArg)
{
CMD_UTILS_START_CONSOLE;
const auto fields = parseFieldDenotations(parameterValues, true);

View File

@ -8,10 +8,7 @@
#include <vector>
namespace ApplicationUtilities {
typedef std::vector<std::string> StringVector;
class Argument;
}
namespace Cli {
@ -35,21 +32,24 @@ struct SetTagInfoArgs
ApplicationUtilities::Argument minPaddingArg;
ApplicationUtilities::Argument maxPaddingArg;
ApplicationUtilities::Argument prefPaddingArg;
ApplicationUtilities::Argument tagPosArg;
ApplicationUtilities::Argument tagPosValueArg;
ApplicationUtilities::Argument forceTagPosArg;
ApplicationUtilities::Argument indexPosArg;
ApplicationUtilities::Argument tagPosArg;
ApplicationUtilities::Argument indexPosValueArg;
ApplicationUtilities::Argument forceIndexPosArg;
ApplicationUtilities::Argument indexPosArg;
ApplicationUtilities::Argument forceRewriteArg;
ApplicationUtilities::Argument valuesArg;
ApplicationUtilities::Argument setTagInfoArg;
};
void printFieldNames(const ApplicationUtilities::StringVector &parameterValues);
void displayFileInfo(const ApplicationUtilities::StringVector &, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
void generateFileInfo(const ApplicationUtilities::StringVector &parameterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg);
void displayTagInfo(const ApplicationUtilities::StringVector &parameterValues, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
void setTagInfo(const ApplicationUtilities::StringVector &parameterValues, const Cli::SetTagInfoArgs &args);
void extractField(const ApplicationUtilities::StringVector &parameterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &verboseArg);
void removeBackupFiles(const ApplicationUtilities::StringVector &parameterValues, const ApplicationUtilities::Argument &recursiveArg);
void printFieldNames(const std::vector<const char *> &parameterValues);
void displayFileInfo(const std::vector<const char *> &, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
void generateFileInfo(const std::vector<const char *> &parameterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &validateArg);
void displayTagInfo(const std::vector<const char *> &parameterValues, const ApplicationUtilities::Argument &filesArg, const ApplicationUtilities::Argument &verboseArg);
void setTagInfo(const std::vector<const char *> &parameterValues, const Cli::SetTagInfoArgs &args);
void extractField(const std::vector<const char *> &parameterValues, const ApplicationUtilities::Argument &inputFileArg, const ApplicationUtilities::Argument &outputFileArg, const ApplicationUtilities::Argument &verboseArg);
void removeBackupFiles(const std::vector<const char *> &parameterValues, const ApplicationUtilities::Argument &recursiveArg);
}