fix(glossary): handle save errors and improve playlist controls
This commit is contained in:
1 parent
3d8f644d8d
commit
309801d059
7 files changed
+204
-33
No files matched your search
@@ -56,12 +56,28 @@ GlossaryStore::Glossary GlossaryStore::load(const QString &directory)
|
||||
bool GlossaryStore::save(const Glossary &glossary, QString *error)
|
||||
{
|
||||
const QString directory = QDir::cleanPath(glossary.directory);
|
||||
for (const Entry &entry : glossary.entries) {
|
||||
if (entry.source.trimmed().isEmpty() || entry.target.trimmed().isEmpty()) {
|
||||
if (error) {
|
||||
*error = QStringLiteral("Each glossary term must have both an original and a translation.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const QString path = pathForDirectory(directory);
|
||||
QDir().mkpath(QFileInfo(path).absolutePath());
|
||||
if (!QDir().mkpath(QFileInfo(path).absolutePath()) && !QFileInfo::exists(QFileInfo(path).absolutePath())) {
|
||||
if (error) {
|
||||
*error = QStringLiteral("Could not create the glossary storage directory.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
QSaveFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly) || file.write(QJsonDocument(glossaryJson({directory, glossary.entries})).toJson(QJsonDocument::Indented)) < 0 || !file.commit()) {
|
||||
if (error) {
|
||||
*error = file.errorString();
|
||||
if (error->isEmpty()) {
|
||||
*error = QStringLiteral("Could not write the glossary file.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,25 +139,51 @@ QString TranslationService::glossaryDirectory() const
|
||||
return m_glossary.directory;
|
||||
}
|
||||
|
||||
QString TranslationService::glossaryError() const
|
||||
{
|
||||
return m_glossaryError;
|
||||
}
|
||||
|
||||
void TranslationService::loadGlossary(const QUrl &videoUrl)
|
||||
{
|
||||
const QString directory = videoUrl.isLocalFile() ? QFileInfo(videoUrl.toLocalFile()).absolutePath() : QString();
|
||||
m_glossary = directory.isEmpty() ? GlossaryStore::Glossary{} : GlossaryStore::load(directory);
|
||||
if (!m_glossaryError.isEmpty()) {
|
||||
m_glossaryError.clear();
|
||||
Q_EMIT glossaryErrorChanged();
|
||||
}
|
||||
Q_EMIT glossaryChanged();
|
||||
}
|
||||
|
||||
void TranslationService::saveGlossary(const QVariantList &entries)
|
||||
bool TranslationService::saveGlossary(const QVariantList &entries)
|
||||
{
|
||||
QList<GlossaryStore::Entry> result;
|
||||
for (const QVariant &value : entries) {
|
||||
const QVariantMap map = value.toMap();
|
||||
result.append({map.value(u"source"_s).toString().trimmed(), map.value(u"target"_s).toString().trimmed()});
|
||||
}
|
||||
m_glossary.entries = result;
|
||||
if (!m_glossary.directory.isEmpty()) {
|
||||
GlossaryStore::save(m_glossary);
|
||||
|
||||
GlossaryStore::Glossary candidate = m_glossary;
|
||||
candidate.entries = result;
|
||||
if (!candidate.directory.isEmpty()) {
|
||||
QString error;
|
||||
if (!GlossaryStore::save(candidate, &error)) {
|
||||
const QString message = error.isEmpty() ? i18n("Could not save the translation glossary.")
|
||||
: i18n("Could not save the translation glossary: %1", error);
|
||||
if (m_glossaryError != message) {
|
||||
m_glossaryError = message;
|
||||
Q_EMIT glossaryErrorChanged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_glossary = candidate;
|
||||
if (!m_glossaryError.isEmpty()) {
|
||||
m_glossaryError.clear();
|
||||
Q_EMIT glossaryErrorChanged();
|
||||
}
|
||||
Q_EMIT glossaryChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TranslationService::clearGlossary()
|
||||
|
||||
@@ -34,6 +34,7 @@ class TranslationService : public QObject
|
||||
Q_PROPERTY(bool fetchingModels READ isFetchingModels NOTIFY fetchingModelsChanged)
|
||||
Q_PROPERTY(QVariantList glossaryEntries READ glossaryEntries NOTIFY glossaryChanged)
|
||||
Q_PROPERTY(QString glossaryDirectory READ glossaryDirectory NOTIFY glossaryChanged)
|
||||
Q_PROPERTY(QString glossaryError READ glossaryError NOTIFY glossaryErrorChanged)
|
||||
|
||||
public:
|
||||
explicit TranslationService(QObject *parent = nullptr);
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
bool isFetchingModels() const;
|
||||
QVariantList glossaryEntries() const;
|
||||
QString glossaryDirectory() const;
|
||||
QString glossaryError() const;
|
||||
|
||||
// \a track is an entry of MpvItem::subtitleTracks.
|
||||
Q_INVOKABLE void translate(const QUrl &videoUrl, const QVariantMap &track, const QString &mediaTitle);
|
||||
@@ -56,7 +58,7 @@ public:
|
||||
Q_INVOKABLE void fetchModels();
|
||||
Q_INVOKABLE void clearError();
|
||||
Q_INVOKABLE void loadGlossary(const QUrl &videoUrl);
|
||||
Q_INVOKABLE void saveGlossary(const QVariantList &entries);
|
||||
Q_INVOKABLE bool saveGlossary(const QVariantList &entries);
|
||||
Q_INVOKABLE void clearGlossary();
|
||||
|
||||
Q_SIGNALS:
|
||||
@@ -67,6 +69,7 @@ Q_SIGNALS:
|
||||
void availableModelsChanged();
|
||||
void fetchingModelsChanged();
|
||||
void glossaryChanged();
|
||||
void glossaryErrorChanged();
|
||||
void translated(const QUrl &subtitleUrl, bool fromCache);
|
||||
|
||||
private:
|
||||
@@ -98,6 +101,7 @@ private:
|
||||
double m_progress = 0.0;
|
||||
QString m_statusText;
|
||||
QString m_errorText;
|
||||
QString m_glossaryError;
|
||||
QStringList m_availableModels;
|
||||
bool m_fetchingModels = false;
|
||||
GlossaryStore::Glossary m_glossary;
|
||||
|
||||
Reference in new issue
Block a user