Allow renaming file via `set --script …`
This allows doing what the GUI renaming utilitiy does on the command-line. If only renaming is wanted
This commit is contained in:
parent
b5f9158106
commit
72dcbbbd81
14
README.md
14
README.md
|
@ -369,12 +369,13 @@ Here are some Bash examples which illustrate getting and setting tag information
|
||||||
- The script needs to be ECMAScript as supported by the Qt framework.
|
- The script needs to be ECMAScript as supported by the Qt framework.
|
||||||
- This feature requires the tag editor to be configured with Qt QML as JavaScript provider at
|
- This feature requires the tag editor to be configured with Qt QML as JavaScript provider at
|
||||||
compile time. Checkout the build instructions under "Building with Qt GUI" for details.
|
compile time. Checkout the build instructions under "Building with Qt GUI" for details.
|
||||||
- The script needs to export a `main()` function. This function gets executed for every file and
|
- The script needs to export a `main()` function. This function is invoked for every file and
|
||||||
passed an object representing this file as first argument.
|
passed an object representing the current file as first argument.
|
||||||
- Checkout the file `testfiles/set-tags.js` in this repository for an example that applies basic
|
- Checkout the file `testfiles/set-tags.js` in this repository for an example that applies basic
|
||||||
fixes and tries to fetch lyrics and cover art.
|
fixes and tries to fetch lyrics and cover art.
|
||||||
- The option `--pedantic debug` is not required but useful for debugging. You may also add
|
- For debugging, the option `--pedantic debug` is very useful. You may also add
|
||||||
`--script-settings dryRun=1` and use that setting within the script as shown in the example.
|
`--script-settings dryRun=1` and check for that setting within the script as shown in the
|
||||||
|
mentioned example script.
|
||||||
- Common tag fields are exposed as object properties as shown in the mentioned example.
|
- Common tag fields are exposed as object properties as shown in the mentioned example.
|
||||||
- Only properties for fields that are supported by the tag are added to the "fields" object.
|
- Only properties for fields that are supported by the tag are added to the "fields" object.
|
||||||
- Adding properties of unsupported fields manually does not work; those will just be ignored.
|
- Adding properties of unsupported fields manually does not work; those will just be ignored.
|
||||||
|
@ -394,6 +395,11 @@ Here are some Bash examples which illustrate getting and setting tag information
|
||||||
- The script is executed before any other modifications are applied. So if you also specify
|
- The script is executed before any other modifications are applied. So if you also specify
|
||||||
values as usual (via `--values`) then these values have precedence over values set by the
|
values as usual (via `--values`) then these values have precedence over values set by the
|
||||||
script.
|
script.
|
||||||
|
- It is also possible to rename the file (via e.g. `file.rename(newPath)`). This will be done
|
||||||
|
immediately and also if `main()` returns a falsy value (so it is possible to only rename a
|
||||||
|
file without modifying it by returning a falsy value). If the specified path is relative, it
|
||||||
|
is interpreted relative to current directory of the file (and *not* to the current working
|
||||||
|
directory of the tag editor).
|
||||||
|
|
||||||
##### Further useful commands
|
##### Further useful commands
|
||||||
* Let the tag editor return with a non-zero exit code even if only non-fatal problems have been encountered
|
* Let the tag editor return with a non-zero exit code even if only non-fatal problems have been encountered
|
||||||
|
|
|
@ -494,6 +494,7 @@ public:
|
||||||
private:
|
private:
|
||||||
static void addWarnings(Diagnostics &diag, const std::string &context, const QList<QQmlError> &warnings);
|
static void addWarnings(Diagnostics &diag, const std::string &context, const QList<QQmlError> &warnings);
|
||||||
|
|
||||||
|
const SetTagInfoArgs &args;
|
||||||
int argc;
|
int argc;
|
||||||
QCoreApplication app;
|
QCoreApplication app;
|
||||||
Diagnostics diag;
|
Diagnostics diag;
|
||||||
|
@ -510,7 +511,8 @@ private:
|
||||||
* - Logs status/problems directly in accordance with other parts of the CLI.
|
* - Logs status/problems directly in accordance with other parts of the CLI.
|
||||||
*/
|
*/
|
||||||
JavaScriptProcessor::JavaScriptProcessor(const SetTagInfoArgs &args)
|
JavaScriptProcessor::JavaScriptProcessor(const SetTagInfoArgs &args)
|
||||||
: argc(0)
|
: args(args)
|
||||||
|
, argc(0)
|
||||||
, app(argc, nullptr)
|
, app(argc, nullptr)
|
||||||
, utility(new UtilityObject(&engine))
|
, utility(new UtilityObject(&engine))
|
||||||
{
|
{
|
||||||
|
@ -567,7 +569,7 @@ JavaScriptProcessor::JavaScriptProcessor(const SetTagInfoArgs &args)
|
||||||
*/
|
*/
|
||||||
QJSValue JavaScriptProcessor::callMain(MediaFileInfo &mediaFileInfo, Diagnostics &diag)
|
QJSValue JavaScriptProcessor::callMain(MediaFileInfo &mediaFileInfo, Diagnostics &diag)
|
||||||
{
|
{
|
||||||
auto fileInfoObject = MediaFileInfoObject(mediaFileInfo, diag, &engine);
|
auto fileInfoObject = MediaFileInfoObject(mediaFileInfo, diag, &engine, args.quietArg.isPresent());
|
||||||
auto fileInfoObjectValue = engine.newQObject(&fileInfoObject);
|
auto fileInfoObjectValue = engine.newQObject(&fileInfoObject);
|
||||||
auto context = argsToString("executing JavaScript for ", mediaFileInfo.fileName());
|
auto context = argsToString("executing JavaScript for ", mediaFileInfo.fileName());
|
||||||
utility->setDiag(&context, &diag);
|
utility->setDiag(&context, &diag);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <c++utilities/conversion/binaryconversion.h>
|
#include <c++utilities/conversion/binaryconversion.h>
|
||||||
#include <c++utilities/conversion/conversionexception.h>
|
#include <c++utilities/conversion/conversionexception.h>
|
||||||
|
#include <c++utilities/conversion/stringbuilder.h>
|
||||||
|
#include <c++utilities/io/path.h>
|
||||||
|
|
||||||
#include <qtutilities/misc/compat.h>
|
#include <qtutilities/misc/compat.h>
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@
|
||||||
#include <QJSValueIterator>
|
#include <QJSValueIterator>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -558,11 +561,13 @@ void TagObject::applyChanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaFileInfoObject::MediaFileInfoObject(TagParser::MediaFileInfo &mediaFileInfo, TagParser::Diagnostics &diag, QJSEngine *engine, QObject *parent)
|
MediaFileInfoObject::MediaFileInfoObject(
|
||||||
|
TagParser::MediaFileInfo &mediaFileInfo, TagParser::Diagnostics &diag, QJSEngine *engine, bool quiet, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_f(mediaFileInfo)
|
, m_f(mediaFileInfo)
|
||||||
, m_diag(diag)
|
, m_diag(diag)
|
||||||
, m_engine(engine)
|
, m_engine(engine)
|
||||||
|
, m_quiet(quiet)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,4 +626,27 @@ void MediaFileInfoObject::applyChanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MediaFileInfoObject::rename(const QString &newPath)
|
||||||
|
{
|
||||||
|
const auto from = m_f.path();
|
||||||
|
const auto fromNative = std::filesystem::path(CppUtilities::makeNativePath(from));
|
||||||
|
const auto toRelUtf8 = newPath.toUtf8();
|
||||||
|
const auto toRelView = CppUtilities::PathStringView(toRelUtf8.data(), static_cast<std::size_t>(toRelUtf8.size()));
|
||||||
|
const auto toNative = fromNative.parent_path().append(CppUtilities::makeNativePath(toRelView));
|
||||||
|
const auto toView = CppUtilities::extractNativePath(toNative.native());
|
||||||
|
try {
|
||||||
|
m_f.stream().close();
|
||||||
|
std::filesystem::rename(fromNative, toNative);
|
||||||
|
m_f.reportPathChanged(toView);
|
||||||
|
m_f.stream().open(m_f.path(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
|
m_diag.emplace_back(TagParser::DiagLevel::Critical, e.what(), CppUtilities::argsToString("renaming \"", from, "\" to \"", toView));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_quiet) {
|
||||||
|
std::cout << " - Renamed \"" << from << "\" to \"" << toView << "\"\n";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Cli
|
} // namespace Cli
|
||||||
|
|
|
@ -193,7 +193,8 @@ class MediaFileInfoObject : public QObject {
|
||||||
Q_PROPERTY(QList<TagObject *> tags READ tags)
|
Q_PROPERTY(QList<TagObject *> tags READ tags)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MediaFileInfoObject(TagParser::MediaFileInfo &mediaFileInfo, TagParser::Diagnostics &diag, QJSEngine *engine, QObject *parent = nullptr);
|
explicit MediaFileInfoObject(
|
||||||
|
TagParser::MediaFileInfo &mediaFileInfo, TagParser::Diagnostics &diag, QJSEngine *engine, bool quiet, QObject *parent = nullptr);
|
||||||
~MediaFileInfoObject() override;
|
~MediaFileInfoObject() override;
|
||||||
|
|
||||||
TagParser::MediaFileInfo &fileInfo();
|
TagParser::MediaFileInfo &fileInfo();
|
||||||
|
@ -207,12 +208,14 @@ public:
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void applyChanges();
|
void applyChanges();
|
||||||
|
bool rename(const QString &newPath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TagParser::MediaFileInfo &m_f;
|
TagParser::MediaFileInfo &m_f;
|
||||||
TagParser::Diagnostics &m_diag;
|
TagParser::Diagnostics &m_diag;
|
||||||
QJSEngine *m_engine;
|
QJSEngine *m_engine;
|
||||||
QList<TagObject *> m_tags;
|
QList<TagObject *> m_tags;
|
||||||
|
bool m_quiet;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline TagParser::MediaFileInfo &MediaFileInfoObject::fileInfo()
|
inline TagParser::MediaFileInfo &MediaFileInfoObject::fileInfo()
|
||||||
|
|
Loading…
Reference in New Issue