From 8442e66c8d8accf07538d6c46407c8b465145dc8 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:34:44 +0200 Subject: [PATCH 01/10] Define language code types and allow to access language codes by type --- libqnapi/src/subtitlelanguage.cpp | 260 +++++++++++++++--------------- libqnapi/src/subtitlelanguage.h | 23 ++- 2 files changed, 144 insertions(+), 139 deletions(-) diff --git a/libqnapi/src/subtitlelanguage.cpp b/libqnapi/src/subtitlelanguage.cpp index 9ab5ea8..1c95829 100644 --- a/libqnapi/src/subtitlelanguage.cpp +++ b/libqnapi/src/subtitlelanguage.cpp @@ -24,185 +24,179 @@ void SubtitleLanguage::setLanguage(QString source) { idx = -1; if (source.length() == 2) { - idx = codes2l.indexOf(source.toLower()); + idx = strings[LCT_TWO_LETTER].indexOf(source.toLower()); } else if (source.length() == 3) { - idx = codes3l.indexOf(source.toLower()); + idx = strings[LCT_TRI_LETTER].indexOf(source.toLower()); } else { - idx = names.indexOf(source); + idx = strings[LCT_NONE].indexOf(source); } } -QString SubtitleLanguage::toTwoLetter() { +/** + * Convert selected language to a string. + * + * @param langCodeType Type of language code or #LCT_NONE to get full name of + * the langage. + * @return Language string or empty string if selected language coundn't be + * recognized or wasn't selected at all. + * + * @see #SubtitleLanguage::setLanguage + */ +QString SubtitleLanguage::toString(LangCodeType langCodeType) const { if (idx > -1) { - return codes2l.at(idx); + return strings.at(langCodeType).at(idx); } return ""; } -QString SubtitleLanguage::toTriLetter() { - if (idx > -1) { - return codes3l.at(idx); - } - return ""; -} - -QString SubtitleLanguage::toFullName() { - if (idx > -1) { - return names.at(idx); - } - return ""; -} - -QStringList SubtitleLanguage::listLanguages() { return names; } - -QStringList SubtitleLanguage::listLanguageTwoLetterCodes() { return codes2l; } +QStringList SubtitleLanguage::listLanguages(LangCodeType langCodeType) const { return strings.at(langCodeType); } void SubtitleLanguage::fill_tables() { - codes2l << "sq"; - codes3l << "alb"; - names << QObject::tr("Albanian"); + strings[LCT_TWO_LETTER] << "sq"; + strings[LCT_TRI_LETTER] << "alb"; + strings[LCT_NONE] << QObject::tr("Albanian"); - codes2l << "en"; - codes3l << "eng"; - names << QObject::tr("English"); + strings[LCT_TWO_LETTER] << "en"; + strings[LCT_TRI_LETTER] << "eng"; + strings[LCT_NONE] << QObject::tr("English"); - codes2l << "ar"; - codes3l << "ara"; - names << QObject::tr("Arabic"); + strings[LCT_TWO_LETTER] << "ar"; + strings[LCT_TRI_LETTER] << "ara"; + strings[LCT_NONE] << QObject::tr("Arabic"); - codes2l << "bg"; - codes3l << "bul"; - names << QObject::tr("Bulgarian"); + strings[LCT_TWO_LETTER] << "bg"; + strings[LCT_TRI_LETTER] << "bul"; + strings[LCT_NONE] << QObject::tr("Bulgarian"); - codes2l << "zh"; - codes3l << "chi"; - names << QObject::tr("Chinese"); + strings[LCT_TWO_LETTER] << "zh"; + strings[LCT_TRI_LETTER] << "chi"; + strings[LCT_NONE] << QObject::tr("Chinese"); - codes2l << "hr"; - codes3l << "hrv"; - names << QObject::tr("Croatian"); + strings[LCT_TWO_LETTER] << "hr"; + strings[LCT_TRI_LETTER] << "hrv"; + strings[LCT_NONE] << QObject::tr("Croatian"); - codes2l << "cs"; - codes3l << "cze"; - names << QObject::tr("Czech"); + strings[LCT_TWO_LETTER] << "cs"; + strings[LCT_TRI_LETTER] << "cze"; + strings[LCT_NONE] << QObject::tr("Czech"); - codes2l << "da"; - codes3l << "dan"; - names << QObject::tr("Danish"); + strings[LCT_TWO_LETTER] << "da"; + strings[LCT_TRI_LETTER] << "dan"; + strings[LCT_NONE] << QObject::tr("Danish"); - codes2l << "et"; - codes3l << "est"; - names << QObject::tr("Estonian"); + strings[LCT_TWO_LETTER] << "et"; + strings[LCT_TRI_LETTER] << "est"; + strings[LCT_NONE] << QObject::tr("Estonian"); - codes2l << "fi"; - codes3l << "fin"; - names << QObject::tr("Finnish"); + strings[LCT_TWO_LETTER] << "fi"; + strings[LCT_TRI_LETTER] << "fin"; + strings[LCT_NONE] << QObject::tr("Finnish"); - codes2l << "fr"; - codes3l << "fre"; - names << QObject::tr("French"); + strings[LCT_TWO_LETTER] << "fr"; + strings[LCT_TRI_LETTER] << "fre"; + strings[LCT_NONE] << QObject::tr("French"); - codes2l << "gl"; - codes3l << "glg"; - names << QObject::tr("Galician"); + strings[LCT_TWO_LETTER] << "gl"; + strings[LCT_TRI_LETTER] << "glg"; + strings[LCT_NONE] << QObject::tr("Galician"); - codes2l << "el"; - codes3l << "ell"; - names << QObject::tr("Greek"); + strings[LCT_TWO_LETTER] << "el"; + strings[LCT_TRI_LETTER] << "ell"; + strings[LCT_NONE] << QObject::tr("Greek"); - codes2l << "he"; - codes3l << "heb"; - names << QObject::tr("Hebrew"); + strings[LCT_TWO_LETTER] << "he"; + strings[LCT_TRI_LETTER] << "heb"; + strings[LCT_NONE] << QObject::tr("Hebrew"); - codes2l << "es"; - codes3l << "spa"; - names << QObject::tr("Spanish"); + strings[LCT_TWO_LETTER] << "es"; + strings[LCT_TRI_LETTER] << "spa"; + strings[LCT_NONE] << QObject::tr("Spanish"); - codes2l << "nl"; - codes3l << "dut"; - names << QObject::tr("Dutch"); + strings[LCT_TWO_LETTER] << "nl"; + strings[LCT_TRI_LETTER] << "dut"; + strings[LCT_NONE] << QObject::tr("Dutch"); - codes2l << "id"; - codes3l << "ind"; - names << QObject::tr("Indonesian"); + strings[LCT_TWO_LETTER] << "id"; + strings[LCT_TRI_LETTER] << "ind"; + strings[LCT_NONE] << QObject::tr("Indonesian"); - codes2l << "ja"; - codes3l << "jpn"; - names << QObject::tr("Japanese"); + strings[LCT_TWO_LETTER] << "ja"; + strings[LCT_TRI_LETTER] << "jpn"; + strings[LCT_NONE] << QObject::tr("Japanese"); - codes2l << "ko"; - codes3l << "kor"; - names << QObject::tr("Korean"); + strings[LCT_TWO_LETTER] << "ko"; + strings[LCT_TRI_LETTER] << "kor"; + strings[LCT_NONE] << QObject::tr("Korean"); - codes2l << "mk"; - codes3l << "mac"; - names << QObject::tr("Macedonian"); + strings[LCT_TWO_LETTER] << "mk"; + strings[LCT_TRI_LETTER] << "mac"; + strings[LCT_NONE] << QObject::tr("Macedonian"); - codes2l << "de"; - codes3l << "ger"; - names << QObject::tr("German"); + strings[LCT_TWO_LETTER] << "de"; + strings[LCT_TRI_LETTER] << "ger"; + strings[LCT_NONE] << QObject::tr("German"); - codes2l << "no"; - codes3l << "nor"; - names << QObject::tr("Norwegian"); + strings[LCT_TWO_LETTER] << "no"; + strings[LCT_TRI_LETTER] << "nor"; + strings[LCT_NONE] << QObject::tr("Norwegian"); - codes2l << "oc"; - codes3l << "oci"; - names << QObject::tr("Occitan"); + strings[LCT_TWO_LETTER] << "oc"; + strings[LCT_TRI_LETTER] << "oci"; + strings[LCT_NONE] << QObject::tr("Occitan"); - codes2l << "fa"; - codes3l << "per"; - names << QObject::tr("Persian (farsi)"); + strings[LCT_TWO_LETTER] << "fa"; + strings[LCT_TRI_LETTER] << "per"; + strings[LCT_NONE] << QObject::tr("Persian (farsi)"); - codes2l << "pl"; - codes3l << "pol"; - names << QObject::tr("Polish"); + strings[LCT_TWO_LETTER] << "pl"; + strings[LCT_TRI_LETTER] << "pol"; + strings[LCT_NONE] << QObject::tr("Polish"); - codes2l << "pt"; - codes3l << "por"; - names << QObject::tr("Portuguese"); + strings[LCT_TWO_LETTER] << "pt"; + strings[LCT_TRI_LETTER] << "por"; + strings[LCT_NONE] << QObject::tr("Portuguese"); - codes2l << "pb"; - codes3l << "pob"; - names << QObject::tr("Portuguese-BR"); + strings[LCT_TWO_LETTER] << "pb"; + strings[LCT_TRI_LETTER] << "pob"; + strings[LCT_NONE] << QObject::tr("Portuguese-BR"); - codes2l << "ru"; - codes3l << "rus"; - names << QObject::tr("Russian"); + strings[LCT_TWO_LETTER] << "ru"; + strings[LCT_TRI_LETTER] << "rus"; + strings[LCT_NONE] << QObject::tr("Russian"); - codes2l << "ro"; - codes3l << "rum"; - names << QObject::tr("Romanian"); + strings[LCT_TWO_LETTER] << "ro"; + strings[LCT_TRI_LETTER] << "rum"; + strings[LCT_NONE] << QObject::tr("Romanian"); - codes2l << "sr"; - codes3l << "scc"; - names << QObject::tr("Serbian"); + strings[LCT_TWO_LETTER] << "sr"; + strings[LCT_TRI_LETTER] << "scc"; + strings[LCT_NONE] << QObject::tr("Serbian"); - codes2l << "sl"; - codes3l << "slv"; - names << QObject::tr("Slovenian"); + strings[LCT_TWO_LETTER] << "sl"; + strings[LCT_TRI_LETTER] << "slv"; + strings[LCT_NONE] << QObject::tr("Slovenian"); - codes2l << "sv"; - codes3l << "swe"; - names << QObject::tr("Swedish"); + strings[LCT_TWO_LETTER] << "sv"; + strings[LCT_TRI_LETTER] << "swe"; + strings[LCT_NONE] << QObject::tr("Swedish"); - codes2l << "sk"; - codes3l << "slo"; - names << QObject::tr("Slovak"); + strings[LCT_TWO_LETTER] << "sk"; + strings[LCT_TRI_LETTER] << "slo"; + strings[LCT_NONE] << QObject::tr("Slovak"); - codes2l << "tr"; - codes3l << "tur"; - names << QObject::tr("Turkish"); + strings[LCT_TWO_LETTER] << "tr"; + strings[LCT_TRI_LETTER] << "tur"; + strings[LCT_NONE] << QObject::tr("Turkish"); - codes2l << "vi"; - codes3l << "vie"; - names << QObject::tr("Vietnamese"); + strings[LCT_TWO_LETTER] << "vi"; + strings[LCT_TRI_LETTER] << "vie"; + strings[LCT_NONE] << QObject::tr("Vietnamese"); - codes2l << "hu"; - codes3l << "hun"; - names << QObject::tr("Hungarian"); + strings[LCT_TWO_LETTER] << "hu"; + strings[LCT_TRI_LETTER] << "hun"; + strings[LCT_NONE] << QObject::tr("Hungarian"); - codes2l << "it"; - codes3l << "ita"; - names << QObject::tr("Italian"); + strings[LCT_TWO_LETTER] << "it"; + strings[LCT_TRI_LETTER] << "ita"; + strings[LCT_NONE] << QObject::tr("Italian"); } diff --git a/libqnapi/src/subtitlelanguage.h b/libqnapi/src/subtitlelanguage.h index 2ef6e0c..ff38c9f 100644 --- a/libqnapi/src/subtitlelanguage.h +++ b/libqnapi/src/subtitlelanguage.h @@ -17,6 +17,15 @@ #include #include +#include + +/** Language code types. */ +enum LangCodeType { + LCT_NONE = 0, ///< No language code. + LCT_TWO_LETTER = 1, ///< Two-letter language code. + LCT_TRI_LETTER = 2, ///< Three-letter language code. + LCT_END, ///< End marker. +}; class SubtitleLanguage { public: @@ -24,15 +33,17 @@ class SubtitleLanguage { void setLanguage(QString source); - QString toTwoLetter(); - QString toTriLetter(); - QString toFullName(); + QString toString(LangCodeType langCodeType = LCT_NONE) const; + + QString toTwoLetter() const { return toString(LCT_TWO_LETTER); } + QString toTriLetter() const { return toString(LCT_TRI_LETTER); } + QString toFullName() const { return toString(LCT_NONE); } - QStringList listLanguages(); - QStringList listLanguageTwoLetterCodes(); + QStringList listLanguages(LangCodeType langCodeType = LCT_NONE) const; + QStringList listLanguageTwoLetterCodes() const { return listLanguages(LCT_TWO_LETTER); } private: - QStringList codes2l, codes3l, names; + std::array strings; int idx; void fill_tables(); From c34756e373467027d8c684404af1436171ddc757 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:45:47 +0200 Subject: [PATCH 02/10] Add "language code in file name" setting to QNapi config and GUI --- gui/src/forms/frmoptions.cpp | 5 ++ gui/ui/frmoptions.ui | 36 ++++++++-- libqnapi/src/config/configreader.cpp | 2 + libqnapi/src/config/configwriter.cpp | 2 + libqnapi/src/config/generalconfig.cpp | 1 + libqnapi/src/config/generalconfig.h | 97 +++++++++++++++++---------- 6 files changed, 104 insertions(+), 39 deletions(-) diff --git a/gui/src/forms/frmoptions.cpp b/gui/src/forms/frmoptions.cpp index abbbf3e..a9bad2c 100644 --- a/gui/src/forms/frmoptions.cpp +++ b/gui/src/forms/frmoptions.cpp @@ -347,6 +347,9 @@ void frmOptions::writeConfig() { ui.cbLangBackup->itemData(ui.cbLangBackup->currentIndex()) .toString()) .setNoBackup(ui.cbNoBackup->isChecked()) + .setLangCodeInFileName( + static_cast( + ui.cbLangCodeInFileName->currentIndex())) .setQuietBatch(ui.cbQuietBatch->isChecked()) .setSearchPolicy( static_cast(ui.cbSearchPolicy->currentIndex())) @@ -419,6 +422,8 @@ void frmOptions::readConfig(const QNapiConfig &config) { ui.cbLangBackup->setCurrentIndex(ui.cbLangBackup->findData( SubtitleLanguage(config.generalConfig().backupLanguage()).toTwoLetter())); ui.cbNoBackup->setChecked(config.generalConfig().noBackup()); + ui.cbLangCodeInFileName->setCurrentIndex( + config.generalConfig().langCodeInFileName()); ui.cbQuietBatch->setChecked(config.generalConfig().quietBatch()); ui.twEngines->clear(); diff --git a/gui/ui/frmoptions.ui b/gui/ui/frmoptions.ui index 38aa510..ca17757 100644 --- a/gui/ui/frmoptions.ui +++ b/gui/ui/frmoptions.ui @@ -28,7 +28,7 @@ General - + Qt::Vertical @@ -41,7 +41,7 @@ - + Do not show any windows while retrieving subtitles in command-line @@ -88,14 +88,14 @@ - + Subtitles file permissions: - + 6 @@ -157,7 +157,7 @@ - + Show icon in the system tray (requires application restart) @@ -274,6 +274,32 @@ + + + + Add language code to subtitle file name: + + + + + + + + No + + + + + Two-letter + + + + + Three-letter + + + + diff --git a/libqnapi/src/config/configreader.cpp b/libqnapi/src/config/configreader.cpp index b31a290..5fd1f89 100644 --- a/libqnapi/src/config/configreader.cpp +++ b/libqnapi/src/config/configreader.cpp @@ -75,6 +75,8 @@ const GeneralConfig ConfigReader::readGeneralConfig( settings.value("qnapi/language", preferredLangCode).toString(), settings.value("qnapi/language_backup", backupLangCode).toString(), settings.value("qnapi/no_backup", false).toBool(), + static_cast( + settings.value("qnapi/lang_code_in_file_name", LCT_NONE).toInt()), settings.value("qnapi/quiet_batch", false).toBool(), static_cast( settings.value("qnapi/search_policy", SP_BREAK_IF_FOUND).toInt()), diff --git a/libqnapi/src/config/configwriter.cpp b/libqnapi/src/config/configwriter.cpp index 3e4a228..0741ff1 100644 --- a/libqnapi/src/config/configwriter.cpp +++ b/libqnapi/src/config/configwriter.cpp @@ -50,6 +50,8 @@ void ConfigWriter::writeGeneralConfig(const GeneralConfig& generalConfig, settings.setValue("qnapi/language", generalConfig.language()); settings.setValue("qnapi/language_backup", generalConfig.backupLanguage()); settings.setValue("qnapi/no_backup", generalConfig.noBackup()); + settings.setValue("qnapi/lang_code_in_file_name", + generalConfig.langCodeInFileName()); settings.setValue("qnapi/quiet_batch", generalConfig.quietBatch()); settings.setValue("qnapi/search_policy", generalConfig.searchPolicy()); settings.setValue("qnapi/download_policy", generalConfig.downloadPolicy()); diff --git a/libqnapi/src/config/generalconfig.cpp b/libqnapi/src/config/generalconfig.cpp index 669d13c..6537061 100644 --- a/libqnapi/src/config/generalconfig.cpp +++ b/libqnapi/src/config/generalconfig.cpp @@ -23,6 +23,7 @@ QString GeneralConfig::toString() const { << "language: " << language() << endl << "backupLanguage: " << backupLanguage() << endl << "noBackup: " << noBackup() << endl + << "langCodeInFileName: " << langCodeInFileName() << endl << "quietBatch: " << quietBatch() << endl << "searchPolicy: " << searchPolicy() << endl << "downloadPolicy: " << downloadPolicy() << endl diff --git a/libqnapi/src/config/generalconfig.h b/libqnapi/src/config/generalconfig.h index 9678133..caddbd6 100644 --- a/libqnapi/src/config/generalconfig.h +++ b/libqnapi/src/config/generalconfig.h @@ -15,6 +15,7 @@ #ifndef GENERALCONFIG_H #define GENERALCONFIG_H +#include "../subtitlelanguage.h" #include enum SearchPolicy { @@ -37,6 +38,7 @@ class GeneralConfig { QString language_; QString backupLanguage_; bool noBackup_; + LangCodeType langCodeInFileName_; bool quietBatch_; SearchPolicy searchPolicy_; DownloadPolicy downloadPolicy_; @@ -48,7 +50,8 @@ class GeneralConfig { GeneralConfig(const QString& uiLanguage, const QString& p7zipPath, const QString& tmpPath, const QString& language, const QString& backupLanguage, const bool& noBackup, - const bool& quietBatch, const SearchPolicy& searchPolicy, + const LangCodeType& langCodeInFileName, const bool& quietBatch, + const SearchPolicy& searchPolicy, const DownloadPolicy& downloadPolicy, const bool& changePermissionsEnabled, const QString& changePermissionsTo) @@ -58,18 +61,37 @@ class GeneralConfig { language_(language), backupLanguage_(backupLanguage), noBackup_(noBackup), + langCodeInFileName_(langCodeInFileName), quietBatch_(quietBatch), searchPolicy_(searchPolicy), downloadPolicy_(downloadPolicy), changePermissionsEnabled_(changePermissionsEnabled), changePermissionsTo_(changePermissionsTo) {} + /* TODO: Fill in versions. */ + /** + * @deprecated Since X.X.X. Will be removed in X.X.X. + * Use constructor that accepts #LangCodeType. + */ + Q_DECL_DEPRECATED_X("use constructor that accepts LangCodeType") + GeneralConfig(const QString& uiLanguage, const QString& p7zipPath, + const QString& tmpPath, const QString& language, + const QString& backupLanguage, const bool& noBackup, + const bool& quietBatch, const SearchPolicy& searchPolicy, + const DownloadPolicy& downloadPolicy, + const bool& changePermissionsEnabled, + const QString& changePermissionsTo) + : GeneralConfig(uiLanguage, p7zipPath, tmpPath, language, backupLanguage, + noBackup, LCT_NONE, quietBatch, searchPolicy, downloadPolicy, + changePermissionsEnabled, changePermissionsTo) {} + QString uiLanguage() const { return uiLanguage_; } QString p7zipPath() const { return p7zipPath_; } QString tmpPath() const { return tmpPath_; } QString language() const { return language_; } QString backupLanguage() const { return backupLanguage_; } bool noBackup() const { return noBackup_; } + LangCodeType langCodeInFileName() const { return langCodeInFileName_; } bool quietBatch() const { return quietBatch_; } SearchPolicy searchPolicy() const { return searchPolicy_; } DownloadPolicy downloadPolicy() const { return downloadPolicy_; } @@ -78,72 +100,79 @@ class GeneralConfig { const GeneralConfig setUiLanguage(const QString& uiLanguage) const { return GeneralConfig(uiLanguage, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setP7zipPath(const QString& p7zipPath) const { return GeneralConfig(uiLanguage_, p7zipPath, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setTmpPath(const QString& tmpPath) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setLanguage(const QString& language) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setBackupLanguage(const QString& backupLanguage) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setNoBackup(const bool& noBackup) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); + } + const GeneralConfig setLangCodeInFileName( + const LangCodeType& langCodeInFileName) const { + return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, + backupLanguage_, noBackup_, langCodeInFileName, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setQuietBatch(const bool& quietBatch) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setSearchPolicy(const SearchPolicy& searchPolicy) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setDownloadPolicy( const DownloadPolicy& downloadPolicy) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy, changePermissionsEnabled_, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy, + changePermissionsEnabled_, changePermissionsTo_); } const GeneralConfig setChangePermissionsEnabled( const bool& changePermissionsEnabled) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled, - changePermissionsTo_); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled, changePermissionsTo_); } const GeneralConfig setChangePermissionsTo( const QString& changePermissionsTo) const { return GeneralConfig(uiLanguage_, p7zipPath_, tmpPath_, language_, - backupLanguage_, noBackup_, quietBatch_, searchPolicy_, - downloadPolicy_, changePermissionsEnabled_, - changePermissionsTo); + backupLanguage_, noBackup_, langCodeInFileName_, + quietBatch_, searchPolicy_, downloadPolicy_, + changePermissionsEnabled_, changePermissionsTo); } QString toString() const; From 73b5363858dcb0b91be24b55802f757ec66b1548 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:47:10 +0200 Subject: [PATCH 03/10] Add support for language codes in subtitles file names to subtitle matcher --- libqnapi/src/libqnapi.cpp | 1 + libqnapi/src/subtitlematcher.cpp | 50 ++++++++++++++++++++++++++------ libqnapi/src/subtitlematcher.h | 27 +++++++++++++++-- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/libqnapi/src/libqnapi.cpp b/libqnapi/src/libqnapi.cpp index 22c537d..b7ece4f 100644 --- a/libqnapi/src/libqnapi.cpp +++ b/libqnapi/src/libqnapi.cpp @@ -119,6 +119,7 @@ QSharedPointer LibQNapi::subtitleMatcher( const QNapiConfig& config) { return QSharedPointer( new SubtitleMatcher(config.generalConfig().noBackup(), + config.generalConfig().langCodeInFileName(), config.postProcessingConfig().enabled(), config.postProcessingConfig().subFormat(), config.postProcessingConfig().subExtension(), diff --git a/libqnapi/src/subtitlematcher.cpp b/libqnapi/src/subtitlematcher.cpp index 09dd402..7f8219d 100644 --- a/libqnapi/src/subtitlematcher.cpp +++ b/libqnapi/src/subtitlematcher.cpp @@ -16,12 +16,14 @@ #include SubtitleMatcher::SubtitleMatcher( - bool _noBackup, bool _isPostProcessingEnabled, QString _ppSubFormat, + bool _noBackup, LangCodeType _langCodeInFileName, + bool _isPostProcessingEnabled, QString _ppSubFormat, QString _ppSubExtension, bool _changePermissions, QString _changePermissionsTo, const QSharedPointer& subtitleFormatsRegistry) : noBackup(_noBackup), + langCodeInFileName(_langCodeInFileName), isPostProcessingEnabled(_isPostProcessingEnabled), ppSubFormat(_ppSubFormat), ppSubExtension(_ppSubExtension), @@ -29,8 +31,23 @@ SubtitleMatcher::SubtitleMatcher( changePermissionsTo(_changePermissionsTo), subtitleFormatsRegistry(subtitleFormatsRegistry) {} +/** + * Copy temporary subtitles file into rightful place. + * + * Given temporary file will be placed next to the given video file + * and renamed to match video file name. Optional features will be + * applied accordingly to given settings. + * + * @param subtitlesTmpFilePath Path to the temporary file. + * @param targetMovieFilePath Path to the video file. + * @param subtitlesLanguage Language of the subtitles. Used only when "language + * code in file name" option is different then + * #LCT_NONE. + * @return Success or failure. + */ bool SubtitleMatcher::matchSubtitles(QString subtitlesTmpFilePath, - QString targetMovieFilePath) const { + QString targetMovieFilePath, + QString subtitlesLanguage) const { QFileInfo subtitlesTmpFileInfo(subtitlesTmpFilePath); if (!subtitlesTmpFileInfo.exists()) return false; @@ -38,11 +55,12 @@ bool SubtitleMatcher::matchSubtitles(QString subtitlesTmpFilePath, QString targetExtension = selectTargetExtension(subtitlesTmpFileInfo); QString targetSubtitlesFilePath = - constructSubtitlePath(targetMovieFilePath, targetExtension); + constructSubtitlePath(targetMovieFilePath, targetExtension, + subtitlesLanguage); if (!isWritablePath(targetSubtitlesFilePath)) return false; - removeOrCopy(targetMovieFilePath, targetSubtitlesFilePath); + removeOrCopy(targetMovieFilePath, targetSubtitlesFilePath, subtitlesLanguage); bool result = false; @@ -79,11 +97,23 @@ QString SubtitleMatcher::selectTargetExtension( QString SubtitleMatcher::constructSubtitlePath(QString targetMovieFilePath, QString targetExtension, + QString subtitlesLanguage, QString baseSuffix) const { QFileInfo targetMovieFileInfo(targetMovieFilePath); - return targetMovieFileInfo.path() + QDir::separator() + - targetMovieFileInfo.completeBaseName() + baseSuffix + "." + - targetExtension; + QString ret = targetMovieFileInfo.path() + QDir::separator() + + targetMovieFileInfo.completeBaseName() + baseSuffix + "."; + + if (langCodeInFileName != LCT_NONE) { + QString langCode = SubtitleLanguage(subtitlesLanguage).toString( + langCodeInFileName); + if (!langCode.isEmpty()) { + ret += langCode; + ret += "."; + } + } + + ret += targetExtension; + return ret; } bool SubtitleMatcher::isWritablePath(QString path) const { @@ -92,12 +122,14 @@ bool SubtitleMatcher::isWritablePath(QString path) const { } void SubtitleMatcher::removeOrCopy(QString targetMoviefilePath, - QString targetSubtitlesFilePath) const { + QString targetSubtitlesFilePath, + QString subtitlesLanguage) const { if (QFile::exists(targetSubtitlesFilePath)) { if (!noBackup) { QFileInfo targetSubtitlesFileInfo(targetSubtitlesFilePath); QString newName = constructSubtitlePath( - targetMoviefilePath, targetSubtitlesFileInfo.suffix(), tr("_copy")); + targetMoviefilePath, targetSubtitlesFileInfo.suffix(), + subtitlesLanguage, tr("_copy")); if (QFile::exists(newName)) QFile::remove(newName); diff --git a/libqnapi/src/subtitlematcher.h b/libqnapi/src/subtitlematcher.h index f06b9ff..8eed15a 100644 --- a/libqnapi/src/subtitlematcher.h +++ b/libqnapi/src/subtitlematcher.h @@ -15,6 +15,7 @@ #ifndef SUBTITLE_MATCHER_H #define SUBTITLE_MATCHER_H +#include "subtitlelanguage.h" #include "subconvert/subtitleformatsregistry.h" #include @@ -23,28 +24,48 @@ class SubtitleMatcher : public QObject { Q_OBJECT public: + SubtitleMatcher(bool _noBackup, LangCodeType _langCodeInFileName, + bool _isPostProcessingEnabled, QString _ppSubFormat, + QString _ppSubExtension, bool _changePermissions, + QString _changePermissionsTo, + const QSharedPointer + &subtitleFormatsRegistry); + + /* TODO: Fill in versions. */ + /** + * @deprecated Since X.X.X. Will be removed in X.X.X. + * Use constructor that accepts #LangCodeType. + */ + Q_DECL_DEPRECATED_X("use constructor that accepts LangCodeType") SubtitleMatcher(bool _noBackup, bool _isPostProcessingEnabled, QString _ppSubFormat, QString _ppSubExtension, bool _changePermissions, QString _changePermissionsTo, const QSharedPointer - &subtitleFormatsRegistry); + &subtitleFormatsRegistry) + : SubtitleMatcher(_noBackup, LCT_NONE, _isPostProcessingEnabled, + _ppSubFormat, _ppSubExtension, _changePermissions, + _changePermissionsTo, subtitleFormatsRegistry) {} bool matchSubtitles(QString subtitlesTmpFilePath, - QString targetMovieFilePath) const; + QString targetMovieFilePath, + QString subtitlesLanguage = QString()) const; private: QString selectTargetExtension(QFileInfo subtitlesTmpFileInfo) const; QString constructSubtitlePath(QString targetMovieFilePath, QString targetExtension, + QString subtitlesLanguage, QString baseSuffix = "") const; bool isWritablePath(QString path) const; void removeOrCopy(QString targetMoviefilePath, - QString targetSubtitlesFilePath) const; + QString targetSubtitlesFilePath, + QString subtitlesLanguage) const; bool dryCopy(QString srcFilePath, QString dstFilePath) const; void fixFilePermissions(QString targetSubtitlesFilePath, QString changePermissionsTo) const; bool noBackup; + LangCodeType langCodeInFileName; bool isPostProcessingEnabled; QString ppSubFormat; QString ppSubExtension; From b027f79d60371ac88f2f9c39d5f6552f8bb90cd6 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:48:09 +0200 Subject: [PATCH 04/10] Pass subtitles language to subtitle matcher --- cli/src/clisubtitlesdownloader.cpp | 26 +++++++++++--------------- gui/src/forms/frmprogress.cpp | 7 ++++--- libqnapi/src/qnapi.cpp | 24 ++++++++++++++++-------- libqnapi/src/qnapi.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/cli/src/clisubtitlesdownloader.cpp b/cli/src/clisubtitlesdownloader.cpp index 3e5e16a..a8c5599 100644 --- a/cli/src/clisubtitlesdownloader.cpp +++ b/cli/src/clisubtitlesdownloader.cpp @@ -115,8 +115,7 @@ void printSubtitlesList(const Console& c, QNapi& napi) { } } -Maybe selectSubtitles(const Console& c, const QNapiConfig& config, - QNapi& napi) { +bool selectSubtitles(const Console& c, const QNapiConfig& config, QNapi& napi) { bool showList = false; bool napiShowList = napi.needToShowList(); @@ -129,30 +128,29 @@ Maybe selectSubtitles(const Console& c, const QNapiConfig& config, } if (!showList) { - return just(napi.bestIdx()); + napi.selectSubtitlesByIdx(napi.bestIdx()); } else { QList subtitlesList = napi.listSubtitles(); printSubtitlesList(c, napi); int selIdx = c.inputNumber(tr("Select subtitles to download: "), 0, subtitlesList.size()); - if (selIdx == 0) { - return nothing(); - } else { - return just(selIdx - 1); - } + if (selIdx == 0) return false; + napi.selectSubtitlesByIdx(selIdx - 1); } + + return true; } -int finishSubtitles(int selIdx, const Console& c, QNapi& napi) { +int finishSubtitles(const Console& c, QNapi& napi) { c.printLineOrdinary(tr("Downloading subtitles...")); - if (!napi.download(selIdx)) { + if (!napi.download()) { c.printLineError(tr("Unable to download subtitles!")); return EC_COULD_NOT_DOWNLOAD; } c.printLineOrdinary(tr("Unpacking subtitles...")); - if (!napi.unpack(selIdx)) { + if (!napi.unpack()) { c.printLineError(tr("Failed to unpack subtitles!")); return EC_COULD_NOT_UNARCHIVE; } @@ -197,10 +195,8 @@ int downloadForMovie(const Console& c, const QString& movieFilePath, int i, return EC_SUBTITLES_NOT_FOUND; } - Maybe selIdx = selectSubtitles(c, config, napi); - - if (selIdx) { - return finishSubtitles(selIdx.value(), c, napi); + if (selectSubtitles(c, config, napi)) { + return finishSubtitles(c, napi); } napi.cleanup(); diff --git a/gui/src/forms/frmprogress.cpp b/gui/src/forms/frmprogress.cpp index e5e2453..38cbb31 100644 --- a/gui/src/forms/frmprogress.cpp +++ b/gui/src/forms/frmprogress.cpp @@ -355,11 +355,12 @@ void GetThread::run() { subStatusList << SubtitleInfo::fromFailed(queue[i]); continue; } + napi.selectSubtitlesByIdx(selIdx); emit progressChange(i, queue.size(), 0.5); emit actionChange(tr("Downloading subtitles file...")); - if (!napi.download(selIdx)) { + if (!napi.download()) { ABORT_POINT ++napiFail; @@ -372,7 +373,7 @@ void GetThread::run() { emit progressChange(i, queue.size(), 0.65f); emit actionChange(tr("Unpacking subtitles file...")); - if (!napi.unpack(selIdx)) { + if (!napi.unpack()) { ++napiFail; subStatusList << SubtitleInfo::fromFailed(queue[i]); continue; @@ -398,7 +399,7 @@ void GetThread::run() { } ++napiSuccess; - subStatusList << napi.listSubtitles().at(selIdx); + subStatusList << napi.getSelectedSubtitles(); napi.cleanup(); diff --git a/libqnapi/src/qnapi.cpp b/libqnapi/src/qnapi.cpp index 61ffb3b..28afcc7 100644 --- a/libqnapi/src/qnapi.cpp +++ b/libqnapi/src/qnapi.cpp @@ -61,6 +61,7 @@ void QNapi::clearSubtitlesList() { foreach (QSharedPointer e, enginesList) { e->clearSubtitlesList(); } + currentSubtitles = SubtitleInfo(); } void QNapi::checksum() { @@ -143,15 +144,21 @@ bool QNapi::needToShowList() { int QNapi::bestIdx() { return theBestIdx; } -bool QNapi::download(int i) { - SubtitleInfo s = subtitlesList[i]; - currentEngine = engineByName(s.engine); - if (!currentEngine) return false; - return currentEngine->download(s.id); +/** + * Select subtitles to be processed. + * @param i Index into the list of subtitles. + */ +void QNapi::selectSubtitlesByIdx(int i) { + currentSubtitles = subtitlesList.at(i); } -bool QNapi::unpack(int i) { - return currentEngine ? currentEngine->unpack(subtitlesList[i].id) : false; +bool QNapi::download() { + currentEngine = engineByName(currentSubtitles.engine); + return currentEngine && currentEngine->download(currentSubtitles.id); +} + +bool QNapi::unpack() { + return currentEngine && currentEngine->unpack(currentSubtitles.id); } bool QNapi::matchSubtitles() { @@ -159,7 +166,8 @@ bool QNapi::matchSubtitles() { QSharedPointer matcher = LibQNapi::subtitleMatcher(config); return matcher->matchSubtitles(currentEngine->subtitlesTmp, - currentEngine->movie); + currentEngine->movie, + currentSubtitles.lang); } return false; diff --git a/libqnapi/src/qnapi.h b/libqnapi/src/qnapi.h index 005241c..6072c3a 100644 --- a/libqnapi/src/qnapi.h +++ b/libqnapi/src/qnapi.h @@ -49,11 +49,35 @@ class QNapi { bool needToShowList(); int bestIdx(); - bool download(int i); - bool unpack(int i); + void selectSubtitlesByIdx(int i); + + /** + * Get subtitles selected to be processed. + * @return The subtitles. + */ + const SubtitleInfo& getSelectedSubtitles() const { return currentSubtitles; } + + bool download(); + bool unpack(); bool matchSubtitles(); void postProcessSubtitles() const; + /* TODO: Fill in versions. */ + /** + * @deprecated Since X.X.X. Will be removed in X.X.X. + * Use selectSubtitlesByIdx(i) + download(). + */ + Q_DECL_DEPRECATED_X("use selectSubtitlesByIdx(i) + download()") + bool download(int i) { return selectSubtitlesByIdx(i), download(); } + + /* TODO: Fill in versions. */ + /** + * @deprecated Since X.X.X. Will be removed in X.X.X. + * Use unpack(). + */ + Q_DECL_DEPRECATED_X("use unpack()") + bool unpack(int) { return unpack(); }; + void cleanup(); QString error(); @@ -66,6 +90,7 @@ class QNapi { QString errorMsg; QList> enginesList; QList subtitlesList; + SubtitleInfo currentSubtitles; ///< Subtitles selected to be processed. QSharedPointer currentEngine; // najlepszy indeks napisow From 649c10a6d41d13c3dc4b252693cb9d9e96cecda4 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:49:02 +0200 Subject: [PATCH 05/10] Support language codes in file names while batch-downloading --- gui/src/forms/frmscan.cpp | 21 +++++++++++++++++---- gui/src/forms/frmscan.h | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/gui/src/forms/frmscan.cpp b/gui/src/forms/frmscan.cpp index f349b9d..060b1c0 100644 --- a/gui/src/forms/frmscan.cpp +++ b/gui/src/forms/frmscan.cpp @@ -236,7 +236,11 @@ void frmScan::accept() { QDialog::accept(); } -ScanFilesThread::ScanFilesThread() : staticConfig(LibQNapi::staticConfig()) {} +ScanFilesThread::ScanFilesThread() + : subExtensionFilters(LibQNapi::staticConfig()->subtitleExtensionsFilter() + .split(" ")), + subLangFilter("^()|(\\.[a-z][a-z][a-z]?)$", + QRegularExpression::CaseInsensitiveOption) {} void ScanFilesThread::run() { abort = false; @@ -264,6 +268,14 @@ bool ScanFilesThread::doScan(const QString &path, QDir::Filters filters) { emit folderChange(myPath); + QStringList subtitlesBaseNames; + if (skipIfSubtitlesExists) { + for (const auto &s : QDir(myPath).entryInfoList(subExtensionFilters, + QDir::Files | QDir::Hidden)) { + subtitlesBaseNames << s.completeBaseName(); + } + } + QFileInfoList list = QDir(myPath).entryInfoList(scanFilters, filters); for (QFileInfoList::iterator p = list.begin(); p != list.end(); p++) { @@ -276,9 +288,10 @@ bool ScanFilesThread::doScan(const QString &path, QDir::Filters filters) { bool subtitleFileFound = false; if (skipIfSubtitlesExists) { - foreach (QString subExt, staticConfig->subtitleExtensions()) { - if (QFile::exists((*p).absolutePath() + "/" + - (*p).completeBaseName() + "." + subExt)) { + QString baseName = (*p).completeBaseName(); + for (const auto &subBaseName : subtitlesBaseNames) { + if (subBaseName.startsWith(baseName, Qt::CaseInsensitive) && + subLangFilter.match(subBaseName, baseName.length()).hasMatch()) { subtitleFileFound = true; break; } diff --git a/gui/src/forms/frmscan.h b/gui/src/forms/frmscan.h index 78fd9d2..c520b77 100644 --- a/gui/src/forms/frmscan.h +++ b/gui/src/forms/frmscan.h @@ -52,9 +52,9 @@ class ScanFilesThread : public QNapiThread { private: bool doScan(const QString &path, QDir::Filters filters); - QSharedPointer staticConfig; QString searchPath; - QStringList scanFilters, skipFilters; + QStringList scanFilters, skipFilters, subExtensionFilters; + QRegularExpression subLangFilter; bool skipIfSubtitlesExists, followSymLinks; QSet visited; }; From 459747db68023bee6e89b5ac9ab49059eb162655 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:49:56 +0200 Subject: [PATCH 06/10] Update translation files --- translations/qnapi_it.ts | 200 +++++++++++++++++++++------------------ translations/qnapi_pl.ts | 200 +++++++++++++++++++++------------------ 2 files changed, 220 insertions(+), 180 deletions(-) diff --git a/translations/qnapi_it.ts b/translations/qnapi_it.ts index fce3cba..9495d18 100644 --- a/translations/qnapi_it.ts +++ b/translations/qnapi_it.ts @@ -122,62 +122,62 @@ (cattiva qualità) - + Select subtitles to download: Selezionare sottotitoli da scaricare: - + Downloading subtitles... Scaricamento sottotitoli... - + Unable to download subtitles! Impossibile scaricare sottotitoli! - + Unpacking subtitles... Scompattamento sottotitoli... - + Failed to unpack subtitles! Impossibile scompattare i sottotitoli! - + Post-processing subtitles file... Post-elaborazione file sottotitoli... - + Adjusting subtitles... Adattamento sottotitoli... - + Could not adjust subtitles! Impossibile adattare i sottotitoli! - + Downloading subtitles for '%1' [%2/%3] Scaricamento sottotitoli per '%1' [%2/%3] - + No permission to write to the directory '%1'! Mancano i permessi per scrivere nella cartella '%1'! - + Subtitles not found! Sottotitoli non trovati! - + Processing of remaining %n file(s) was ignored due to critical error. L'elaborazione di un file rimanente è stato ignorato a causa di un errore critico. @@ -282,27 +282,27 @@ Ricerca sottotitoli in lingua alternativa [%1] (%2)... - + Downloading subtitles file... Scaricamento file sottotitoli... - + Unpacking subtitles file... Scompattamento file sottotitoli... - + Post-processing subtitles... Post-elaborazione sottotitoli... - + Adjusting subtitles... Adattamento sottotitoli... - + Could not adjust subtitles! Impossibile adattare i sottotitoli! @@ -503,187 +503,187 @@ Sottotitoli scaricati e processati da QNapi | - + Albanian Albanese - + English Inglese - + Arabic Arabo - + Bulgarian Bulgaro - + Chinese Cinese - + Croatian Croato - + Czech Ceco - + Danish Danese - + Estonian Estone - + Finnish Finlandese - + French Francese - + Galician Gallego - + Greek Greco - + Hebrew Ebraico - + Spanish Spagnolo - + Dutch Olandese - + Indonesian Indonesiano - + Japanese Giapponese - + Korean Coreano - + Macedonian Macedone - + German Tedesco - + Norwegian Norvegese - + Occitan Occitano - + Persian (farsi) Persiano (farsi) - + Polish Polacco - + Portuguese Portoghese - + Portuguese-BR Portoghese-BR - + Russian Russo - + Romanian Romeno - + Serbian Serbo - + Slovenian Sloveno - + Swedish Svedese - + Slovak Slovacco - + Turkish Turco - + Vietnamese Vietnamita - + Hungarian Ungherese - + Italian Italiano @@ -708,7 +708,7 @@ QNapi: operazione conclusa. - + No subtitles found! Nessun sottotitolo trovato! @@ -756,7 +756,7 @@ SubtitleMatcher - + _copy _copia @@ -1204,7 +1204,7 @@ - + Auto-detected based on system language (%1) Autorilevamento in base alla lingua di sistema (%1) @@ -1232,164 +1232,184 @@ Il cambiamento alla lingua della UI verrà attuato al prossimo avvio dell'applicazione - + + Add language code to subtitle file name: + + + + + No + + + + + Two-letter + + + + + Three-letter + + + + Subtitles download engines Motori di scaricamento sottotitoli - + Available engines to download subtitles from: Motori disponibili da cui scaricare sottotitoli: - + Subtitles download policy: Politiche scaricamento sottotitoli: - + Always show a list of available subtitles Mostra sempre una lista di sottotitoli disponibili - + Show a list of available subtitles only if needed Mostra una lista di sottotitoli disponibili solo se necessario - + Always obtain first matching subtitles and never show a list Ottieni sempre i primi sottotitoli corrispondenti e non mostrare mai una lista - + Move up Sposta in su - + Subtitles search policy: Politiche ricerca sottotitoli: - + Move down Sposta in giù - + Information Informazioni - + Configure Configura - + Stop the search after finding a matching subtitles (faster) Interrompi la ricerca dopo aver trovato sottotitoli (veloce) - + Search all available subtitles (slower) Cerca tutti i sottotitoli disponibili (lento) - + Find all subtitles, also in alternative language (slowest) Trova tutti i sottotitoli, anche in lingua alternativa (molto lento) - + Subtitles post-processing Post-elaborazione sottotitoli - + Enable post-processing for downloaded subtitles Abilita post-elaborazione per i sottotitoli scaricati - + Character encoding: Codifica caratteri: - - + + Keep the original Conserva l'originale - + Convert (settings below) Converti (impostazioni sotto) - + Replace diacritic characters with their ASCII equivalents Sostituisci caratteri diacritici con gli equivalenti ASCII - + From: Da: - + To: A: - + Show all available character encodings Mostra tutte le codifiche carattere disponibili - + Subtitles format: Formato sottotitoli: - + Subtitles extension: Estensione sottotitoli: - + Default Predefinita - + Do not add information about QNapi while converting between formats Non aggiungere informazioni su QNapi nella conversione tra formati - + Attempt to automatically detect encoding Tenta di riconoscere automaticamente la codifica - + Remove subtitles lines that contain the following words: Rimuovi linee sottotitoli che contengono le parole seguenti: - + Restore defaults Ripristina predefiniti - + Cancel Annulla - + Save Salva diff --git a/translations/qnapi_pl.ts b/translations/qnapi_pl.ts index 54e8fd6..932d84b 100644 --- a/translations/qnapi_pl.ts +++ b/translations/qnapi_pl.ts @@ -122,62 +122,62 @@ (zle) - + Select subtitles to download: Wybierz napisy do pobrania: - + Downloading subtitles... Pobieranie napisow... - + Unable to download subtitles! Nie udalo sie pobrac napisow! - + Unpacking subtitles... Rozpakowywanie napisow... - + Failed to unpack subtitles! Nie udalo sie rozpakowac napisow! - + Post-processing subtitles file... Przetwarzanie napisow... - + Adjusting subtitles... Dopasowywanie napisów... - + Could not adjust subtitles! Nie udało się dopasować napisów! - + Downloading subtitles for '%1' [%2/%3] Pobieranie napisow dla '%1' [%2/%3] - + No permission to write to the directory '%1'! Brak uprawnień zapisu do katalogu '%1'! - + Subtitles not found! Nie znaleziono napisow! - + Processing of remaining %n file(s) was ignored due to critical error. Pobieranie pozostalego 1 pliku przerwane z powodu bledu. @@ -283,27 +283,27 @@ Szukanie napisów w języku zapasowym [%1] (%2)... - + Downloading subtitles file... Pobieranie napisów dla pliku... - + Unpacking subtitles file... Rozpakowywanie napisów... - + Post-processing subtitles... Przetwarzanie napisów... - + Adjusting subtitles... Dopasowywanie napisów... - + Could not adjust subtitles! Nie udało się dopasować napisów! @@ -519,7 +519,7 @@ QNapi: zakończono. - + No subtitles found! Nie znaleziono napisów! @@ -529,187 +529,187 @@ Napisy pobrane i przetworzone programem QNapi| - + Albanian Albański - + English Angielski - + Arabic Arabski - + Bulgarian Bułgarski - + Chinese Chiński - + Croatian Chorwacki - + Czech Czeski - + Danish Duński - + Estonian Estoński - + Finnish Fiński - + French Francuski - + Galician Galicyjski - + Greek Grecki - + Hebrew Hebrajski - + Spanish Hiszpanski - + Dutch Holenderski - + Indonesian Indonezyjski - + Japanese Japoński - + Korean Koreański - + Macedonian Macedoński - + German Niemiecki - + Norwegian Norweski - + Occitan Oksytański - + Persian (farsi) Perski (farsi) - + Polish Polski - + Portuguese Portugalski - + Portuguese-BR Portugalski-BR - + Russian Rosyjski - + Romanian Rumuński - + Serbian Serbski - + Slovenian Słoweński - + Swedish Szwedzki - + Slovak Słowacki - + Turkish Turecki - + Vietnamese Wietnamski - + Hungarian Węgierski - + Italian Włoski @@ -757,7 +757,7 @@ SubtitleMatcher - + _copy _kopia @@ -1204,7 +1204,7 @@ - + Auto-detected based on system language (%1) Wykryty automatycznie z ustawień systemu (%1) @@ -1232,164 +1232,184 @@ Zmiana języka nastąpi przy następnym uruchomieniu aplikacji - + + Add language code to subtitle file name: + + + + + No + + + + + Two-letter + + + + + Three-letter + + + + Subtitles download engines Moduły pobierania napisów - + Available engines to download subtitles from: Dostępne moduły pobierania napisów: - + Subtitles download policy: Polityka pobierania napisów: - + Always show a list of available subtitles Zawsze pokazuj listę dostępnych napisów - + Show a list of available subtitles only if needed Pokazuj listę dostępnych napisów tylko wtedy, gdy potrzeba - + Always obtain first matching subtitles and never show a list Zawsze pobieraj pierwsze pasujące napisy i nigdy nie pokazuj listy - + Move up Przesuń do góry - + Subtitles search policy: Wyszukiwanie napisów: - + Move down Przesuń na dół - + Information Informacje - + Configure Konfiguruj - + Stop the search after finding a matching subtitles (faster) Przerwij wyszukiwanie po znalezieniu pasujących napisów (szybciej) - + Search all available subtitles (slower) Wyszukaj wszystkie dostępne napisy (wolniej) - + Find all subtitles, also in alternative language (slowest) Wyszukaj wszystkie napisy, także w zapasowym języku (najwolniej) - + Subtitles post-processing Przetwarzanie napisów - + Enable post-processing for downloaded subtitles Włącz przetwarzanie pobranych napisów - + Character encoding: Kodowanie znaków: - - + + Keep the original Pozostaw oryginalne - + Convert (settings below) Konwertuj (ustawienia poniżej) - + Replace diacritic characters with their ASCII equivalents Zamień znaki diakrytyczne na ich odpowiedniki ASCII - + From: Z: - + To: Na: - + Show all available character encodings Pokaż wszystkie dostępne kodowania znaków - + Subtitles format: Format napisów: - + Subtitles extension: Rozszerzenie napisów: - + Default Domyślne - + Do not add information about QNapi while converting between formats Nie dodawaj informacji o QNapi przy konwersji pomiędzy formatami - + Attempt to automatically detect encoding Próbuj automatycznie wykrywać kodowanie źródłowe - + Remove subtitles lines that contain the following words: Usuń z pliku z napisami linie, które zawierają następujące słowa: - + Restore defaults Przywróć domyślne - + Cancel Anuluj - + Save Zapisz From 6a22e90fb3acda75b739cbdb9e13f5aadd6b64ce Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 28 Jul 2020 13:50:31 +0200 Subject: [PATCH 07/10] Polish translation for "language code in file name" setting --- translations/qnapi_pl.qm | Bin 38524 -> 38880 bytes translations/qnapi_pl.ts | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/translations/qnapi_pl.qm b/translations/qnapi_pl.qm index c4adfdf1e8abf72d4432afbf27116d133b6d0cae..bc2baea3dbac810ca3fcd72d5bcf59c0a3e2ae53 100644 GIT binary patch delta 1698 zcmZ`(SyWS36y2F#^71kWqT&Qus0a!PV6low85HLriY`S_gG7vkfCvN-h?GG@Y{5sn ztRrfn&J)g3Tcyt6gchZirLd^lRn!W8fV%9_toE-T@9lT*yZ4@b_SxsYJ0N^~SXkyH zI9=XH>sFcvNFo4pJs>>{M9c)dmnmb4TgBGr&k2s^-@K$&0W@rv>~X?U-;9C!!jGvqFEkEK@Z~5q3b~6Ts-}LCor@d&wjrKOkFw#&#y%TGfttS%@Z(n37lIge+N!5 zU@{A&_7iAke*=W|5)5nH3#2p&R%(v};tD&u9uZiZU4Y`Ve1kwMEb7I-7q|$m4*XzY zkZonQ=e-m|iOO%O_Q$Hj2&GGAdZHINd=FFdgEe zFQUNT6?!_xTE&~D)B>xU?f7LAuN1km?c!V2?Lh21-e0uRHOP^)iHVjhsmcdR8A-a& zCg3waJ0>>rKZ@Li1@U~lDBLew!K5_a0dg)eMddtk2xZo~bpq=%nUb(JU~Ck#!NCSZ zZe=#sO(6k$_!zO)am{_E{$l}07c#dqL#WVU{5EmF{w-2rJ-N#qB=vapEjjG5G_p)Z zYDVx4VqbN>Zz#F#sC4@)5^33SULtYzd?LLertm11Hd#rk!X47quSgn?%`)AVLu4ei zEMOtk({hEMA#u0mOJvD=$!s1EWH~v#f&9N@g<+3YoXUPW#WsN%x zKvuKtzLtD5wMX_+w1URovYsDik^lTz^?NFNs1NIWqz336$ZFs2Cc6w}=k0F+bYAT8 zHlmX-oUL{uvOcBk*=2RGVWJ;<>6jx>(!*Z;T1)x6vDbGH`oClw%!^2e8uo7bO<*m@ z{#N1wjIyy$OQ>9lT$x7lTT1>7~wRbb3>?o+O|licHO2S5>S#{uWLR-F~FzEF%W zA3+9uqnJ=#2RKg4Rp@;lkg8pFG}ZDQQdi$PMP>6v3cpoxPOu6Xk)pUEwa^8$Ptm3e zqw#*lOCixHtya7~%>%}}{CJtm)a*`Wz%frCz)v~t{UJaerqpYG0;FAI<+t&kko&s4sM`w+PwJ~ zcJ$Dk1oh?O9#Xnq{bVgQNPwY7s89Oz^J&_7PUnm$ zq)@EPPf=1~q*2nx$p0-@L@iG-8okZN)Kp^%U!E5@vM=$rBJF>7$fK-D|E~YYq9O0F F(?68={5b#s delta 1455 zcmX9;c}x^{6#jO0c6VlHXIBsesRFKoKyeqa9!0bYf(i=a6-80NAR-`$;Z)di=?cU` zhZ2cY;m7bxjct9p?SC%@NYr4Ivfb9#es{FpR!G z+JNAg1L$vy02ZCWK(9Lxze;BRI1jKAWDfIrVC!<3^U|+?fDtm6&SOBTt!#_oM}V!c zpwlT?Mz5LS1)Vxc;k|EYm>I*C^Wqk@lfn{H^i5X=;!T_6Yr2~`$?2gZt0k$gEoH+#P88gm0 z`T@IlK{JrO$AWp1G*<4!2eUV;p8zq@QlNZ`T~t*8P~4(O_u315;$y)iE2&HF$`p*3 z-phj=vac#rJ8uKq^OQTvCECGXxl=zxT~nk;)=oBEN@ETFrgCM+fBH==Qr^m%L&YDI zccntWUZLy@cmzz=EC05R2U5nUm<}>kLZ!;>#U3)&epPsxmgp6vC#<*X;0q#U!)VDx z;p85qy2jF2m{s>Oh?>IHs>i#D3b$`K`g!hJ@X$kdhRxro0PW$}t=IeV@z8 z842Vc<%;$lC*7BFXHL)naU*v{-$;h2nHx|7Y1TN&$oX|IAxH(p178rpUnT7euF}Dh5x0 z7dh!I{~`G|fC;kT*ci2@VluELS1qOy?Md}&twg-!{;4)buLIWHR?i=uI|ksO4$;#k ziQei(%ZmWdo9dWDX4NaS4jg%IT6PiJW)+mY5y!u%JVy8)woMZ5|I?=b@ z9q{!LL*AbR)B$3s^Lb#Kt+@W+0$@~`m=H_le)bkzTP3F72`4MO6n8DAP-aDl6*DMg zX|JTqobl5L@x~((diepZ`<)*0pP-#Ho2pmTYs2g*H1i^~(Q}Ve;(N4-XNfCMr8cRC zx-)i5llWQI`GGnn%#Vz|NH_aB$(hqH(6J uJ%UYg^1Hv(5$7aLb90t Add language code to subtitle file name: - + Dodawaj kod języka do nazwy pliku napisów: No - + Nie Two-letter - + Dwuliterowy Three-letter - + Trzyliterowy From 54754a237fe785433801cf0a593106a5186b98eb Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Fri, 31 Jul 2020 18:30:40 +0200 Subject: [PATCH 08/10] Fix: Q_DECL_DEPRECATED_X was not in QT 5.2 yet, replace with Q_DECL_DEPRECATED --- libqnapi/src/config/generalconfig.h | 2 +- libqnapi/src/qnapi.h | 4 ++-- libqnapi/src/subtitlematcher.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libqnapi/src/config/generalconfig.h b/libqnapi/src/config/generalconfig.h index caddbd6..5cd4eff 100644 --- a/libqnapi/src/config/generalconfig.h +++ b/libqnapi/src/config/generalconfig.h @@ -73,7 +73,7 @@ class GeneralConfig { * @deprecated Since X.X.X. Will be removed in X.X.X. * Use constructor that accepts #LangCodeType. */ - Q_DECL_DEPRECATED_X("use constructor that accepts LangCodeType") + Q_DECL_DEPRECATED GeneralConfig(const QString& uiLanguage, const QString& p7zipPath, const QString& tmpPath, const QString& language, const QString& backupLanguage, const bool& noBackup, diff --git a/libqnapi/src/qnapi.h b/libqnapi/src/qnapi.h index 6072c3a..5df1d11 100644 --- a/libqnapi/src/qnapi.h +++ b/libqnapi/src/qnapi.h @@ -67,7 +67,7 @@ class QNapi { * @deprecated Since X.X.X. Will be removed in X.X.X. * Use selectSubtitlesByIdx(i) + download(). */ - Q_DECL_DEPRECATED_X("use selectSubtitlesByIdx(i) + download()") + Q_DECL_DEPRECATED bool download(int i) { return selectSubtitlesByIdx(i), download(); } /* TODO: Fill in versions. */ @@ -75,7 +75,7 @@ class QNapi { * @deprecated Since X.X.X. Will be removed in X.X.X. * Use unpack(). */ - Q_DECL_DEPRECATED_X("use unpack()") + Q_DECL_DEPRECATED bool unpack(int) { return unpack(); }; void cleanup(); diff --git a/libqnapi/src/subtitlematcher.h b/libqnapi/src/subtitlematcher.h index 8eed15a..49636fd 100644 --- a/libqnapi/src/subtitlematcher.h +++ b/libqnapi/src/subtitlematcher.h @@ -36,7 +36,7 @@ class SubtitleMatcher : public QObject { * @deprecated Since X.X.X. Will be removed in X.X.X. * Use constructor that accepts #LangCodeType. */ - Q_DECL_DEPRECATED_X("use constructor that accepts LangCodeType") + Q_DECL_DEPRECATED SubtitleMatcher(bool _noBackup, bool _isPostProcessingEnabled, QString _ppSubFormat, QString _ppSubExtension, bool _changePermissions, QString _changePermissionsTo, From 5272ae9efed3259a11a46f6e109bb30e7fe15d39 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 26 Jul 2022 12:03:22 +0200 Subject: [PATCH 09/10] Path utils Module for changing file paths --- gui/src/forms/frmscan.cpp | 18 ++-- gui/src/forms/frmscan.h | 1 - libqnapi/libqnapi.pro | 2 + libqnapi/src/subtitlelanguage.h | 2 + libqnapi/src/subtitlematcher.cpp | 46 +++------ libqnapi/src/subtitlematcher.h | 8 +- libqnapi/src/utils/pathutils.cpp | 70 ++++++++++++++ libqnapi/src/utils/pathutils.h | 160 +++++++++++++++++++++++++++++++ 8 files changed, 258 insertions(+), 49 deletions(-) create mode 100644 libqnapi/src/utils/pathutils.cpp create mode 100644 libqnapi/src/utils/pathutils.h diff --git a/gui/src/forms/frmscan.cpp b/gui/src/forms/frmscan.cpp index 060b1c0..e61120a 100644 --- a/gui/src/forms/frmscan.cpp +++ b/gui/src/forms/frmscan.cpp @@ -14,6 +14,7 @@ #include "frmscan.h" #include "libqnapi.h" +#include "utils/pathutils.h" frmScan::frmScan(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), scanConfig(LibQNapi::loadConfig().scanConfig()) { @@ -238,9 +239,7 @@ void frmScan::accept() { ScanFilesThread::ScanFilesThread() : subExtensionFilters(LibQNapi::staticConfig()->subtitleExtensionsFilter() - .split(" ")), - subLangFilter("^()|(\\.[a-z][a-z][a-z]?)$", - QRegularExpression::CaseInsensitiveOption) {} + .split(" ")) {} void ScanFilesThread::run() { abort = false; @@ -272,7 +271,15 @@ bool ScanFilesThread::doScan(const QString &path, QDir::Filters filters) { if (skipIfSubtitlesExists) { for (const auto &s : QDir(myPath).entryInfoList(subExtensionFilters, QDir::Files | QDir::Hidden)) { - subtitlesBaseNames << s.completeBaseName(); + + QString completeBaseName = s.completeBaseName(); + subtitlesBaseNames << completeBaseName; + + QString completeBaseNameWithoutLang = ChangeFilePath() + .removeLanguageCode().removeExtension().apply(s.fileName()); + if (completeBaseName != completeBaseNameWithoutLang) { + subtitlesBaseNames << completeBaseNameWithoutLang; + } } } @@ -290,8 +297,7 @@ bool ScanFilesThread::doScan(const QString &path, QDir::Filters filters) { if (skipIfSubtitlesExists) { QString baseName = (*p).completeBaseName(); for (const auto &subBaseName : subtitlesBaseNames) { - if (subBaseName.startsWith(baseName, Qt::CaseInsensitive) && - subLangFilter.match(subBaseName, baseName.length()).hasMatch()) { + if (subBaseName.compare(baseName, Qt::CaseInsensitive) == 0) { subtitleFileFound = true; break; } diff --git a/gui/src/forms/frmscan.h b/gui/src/forms/frmscan.h index c520b77..7209b59 100644 --- a/gui/src/forms/frmscan.h +++ b/gui/src/forms/frmscan.h @@ -54,7 +54,6 @@ class ScanFilesThread : public QNapiThread { QString searchPath; QStringList scanFilters, skipFilters, subExtensionFilters; - QRegularExpression subLangFilter; bool skipIfSubtitlesExists, followSymLinks; QSet visited; }; diff --git a/libqnapi/libqnapi.pro b/libqnapi/libqnapi.pro index c939b1b..dc69f89 100644 --- a/libqnapi/libqnapi.pro +++ b/libqnapi/libqnapi.pro @@ -50,6 +50,7 @@ SOURCES += src/config/configreader.cpp \ src/utils/console.cpp \ src/utils/encodingutils.cpp \ src/utils/p7zipdecoder.cpp \ + src/utils/pathutils.cpp \ src/utils/synchttp.cpp \ src/utils/syncxmlrpc.cpp \ src/qnapi.cpp \ @@ -103,6 +104,7 @@ HEADERS += src/config/configreader.h \ src/subtitlepostprocessor.h \ src/utils/console.h \ src/utils/encodingutils.h \ + src/utils/pathutils.h \ src/utils/p7zipdecoder.h \ src/utils/synchttp.h \ src/utils/syncxmlrpc.h \ diff --git a/libqnapi/src/subtitlelanguage.h b/libqnapi/src/subtitlelanguage.h index ff38c9f..63a3a33 100644 --- a/libqnapi/src/subtitlelanguage.h +++ b/libqnapi/src/subtitlelanguage.h @@ -33,6 +33,8 @@ class SubtitleLanguage { void setLanguage(QString source); + bool isValid() const { return idx >= 0; } + QString toString(LangCodeType langCodeType = LCT_NONE) const; QString toTwoLetter() const { return toString(LCT_TWO_LETTER); } diff --git a/libqnapi/src/subtitlematcher.cpp b/libqnapi/src/subtitlematcher.cpp index 7f8219d..a779ea5 100644 --- a/libqnapi/src/subtitlematcher.cpp +++ b/libqnapi/src/subtitlematcher.cpp @@ -13,6 +13,8 @@ *****************************************************************************/ #include "subtitlematcher.h" +#include "utils/pathutils.h" + #include SubtitleMatcher::SubtitleMatcher( @@ -52,15 +54,14 @@ bool SubtitleMatcher::matchSubtitles(QString subtitlesTmpFilePath, if (!subtitlesTmpFileInfo.exists()) return false; - QString targetExtension = selectTargetExtension(subtitlesTmpFileInfo); - - QString targetSubtitlesFilePath = - constructSubtitlePath(targetMovieFilePath, targetExtension, - subtitlesLanguage); + QString targetSubtitlesFilePath = ChangeFilePath() + .setExtension(selectTargetExtension(subtitlesTmpFileInfo)) + .addLanguageCode(subtitlesLanguage, langCodeInFileName) + .apply(targetMovieFilePath); if (!isWritablePath(targetSubtitlesFilePath)) return false; - removeOrCopy(targetMovieFilePath, targetSubtitlesFilePath, subtitlesLanguage); + removeOrCopy(targetSubtitlesFilePath); bool result = false; @@ -95,42 +96,17 @@ QString SubtitleMatcher::selectTargetExtension( return targetExtension; } -QString SubtitleMatcher::constructSubtitlePath(QString targetMovieFilePath, - QString targetExtension, - QString subtitlesLanguage, - QString baseSuffix) const { - QFileInfo targetMovieFileInfo(targetMovieFilePath); - QString ret = targetMovieFileInfo.path() + QDir::separator() + - targetMovieFileInfo.completeBaseName() + baseSuffix + "."; - - if (langCodeInFileName != LCT_NONE) { - QString langCode = SubtitleLanguage(subtitlesLanguage).toString( - langCodeInFileName); - if (!langCode.isEmpty()) { - ret += langCode; - ret += "."; - } - } - - ret += targetExtension; - return ret; -} - bool SubtitleMatcher::isWritablePath(QString path) const { QFileInfo pathFileInfo(path); return QFileInfo(pathFileInfo.absolutePath()).isWritable(); } -void SubtitleMatcher::removeOrCopy(QString targetMoviefilePath, - QString targetSubtitlesFilePath, - QString subtitlesLanguage) const { +void SubtitleMatcher::removeOrCopy(QString targetSubtitlesFilePath) const { if (QFile::exists(targetSubtitlesFilePath)) { if (!noBackup) { - QFileInfo targetSubtitlesFileInfo(targetSubtitlesFilePath); - QString newName = constructSubtitlePath( - targetMoviefilePath, targetSubtitlesFileInfo.suffix(), - subtitlesLanguage, tr("_copy")); - + QString newName = ChangeFilePath() + .addToBaseName(tr("_copy")) + .apply(targetSubtitlesFilePath); if (QFile::exists(newName)) QFile::remove(newName); QFile::rename(targetSubtitlesFilePath, newName); diff --git a/libqnapi/src/subtitlematcher.h b/libqnapi/src/subtitlematcher.h index 49636fd..a59db4a 100644 --- a/libqnapi/src/subtitlematcher.h +++ b/libqnapi/src/subtitlematcher.h @@ -52,14 +52,8 @@ class SubtitleMatcher : public QObject { private: QString selectTargetExtension(QFileInfo subtitlesTmpFileInfo) const; - QString constructSubtitlePath(QString targetMovieFilePath, - QString targetExtension, - QString subtitlesLanguage, - QString baseSuffix = "") const; bool isWritablePath(QString path) const; - void removeOrCopy(QString targetMoviefilePath, - QString targetSubtitlesFilePath, - QString subtitlesLanguage) const; + void removeOrCopy(QString targetSubtitlesFilePath) const; bool dryCopy(QString srcFilePath, QString dstFilePath) const; void fixFilePermissions(QString targetSubtitlesFilePath, QString changePermissionsTo) const; diff --git a/libqnapi/src/utils/pathutils.cpp b/libqnapi/src/utils/pathutils.cpp new file mode 100644 index 0000000..6c64797 --- /dev/null +++ b/libqnapi/src/utils/pathutils.cpp @@ -0,0 +1,70 @@ +/***************************************************************************** +** QNapi +** Copyright (C) 2008-2017 Piotr Krzemiński +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +*****************************************************************************/ + +#include "pathutils.h" + +#include +#include + +QString ChangeFilePath::apply(const QString &path) const { + // search backward and only until directory separator, + // both 'from' and 'to' are inclusive + auto findDot = [&path] (int from, int to = 0) { + for (; from >= to; from--) { + if (path[from] == '.') return from; + if (path[from] == QDir::separator()) break; + } + return -1; + }; + + // position of the dot that precedes file extension + int extDotPos = findDot(path.length() - 1); + // accounts for file extension including the dot + int extLength = extDotPos < 0 ? 0 : path.length() - extDotPos; + + // accounts for existing language code including the preceding dot + int langCodeLength = 0; + if (extDotPos >= 0 && + // no need to bother if we don't need it + (!addToBaseNameStr.isEmpty() || doRemoveLanguageCode)) { + int dotPos = findDot(extDotPos - 1, qMax(0, extDotPos - 4)); + if (dotPos >= 0) { + SubtitleLanguage lang(path.mid(dotPos + 1, extDotPos - dotPos - 1)); + if (lang.isValid()) langCodeLength = extDotPos - dotPos; + } + } + + QString ret = path.left(path.length() - extLength - langCodeLength); + + ret += addToBaseNameStr; + + if (!doRemoveLanguageCode && langCodeLength > 0) { + ret += path.midRef( + path.length() - extLength - langCodeLength, langCodeLength); + } + + if (addLanguageCodeLang.isValid() && addLanguageCodeType != LCT_NONE) { + ret += '.'; + ret += addLanguageCodeLang.toString(addLanguageCodeType); + } + + if (!doRemoveExtension) ret += path.rightRef(extLength); + + if (!addExtensionStr.isEmpty()) { + ret += '.'; + ret += addExtensionStr; + } + + return ret; +} diff --git a/libqnapi/src/utils/pathutils.h b/libqnapi/src/utils/pathutils.h new file mode 100644 index 0000000..f1b3545 --- /dev/null +++ b/libqnapi/src/utils/pathutils.h @@ -0,0 +1,160 @@ +/***************************************************************************** +** QNapi +** Copyright (C) 2008-2017 Piotr Krzemiński +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +*****************************************************************************/ + +#ifndef PATHUTILS_H +#define PATHUTILS_H + +#include "subtitlelanguage.h" + +#include + +class ChangeFilePath { + public: + /** + * Add a given string before file extension and before language code. + * + * Add \a str to the complete base name of the file, excluding language code + * if the file name has one. + * + * Examples (add 'X' string): + * a.b.c -> a.bX.c + * a.eng.c -> aX.eng.c + * a -> aX + * + * If this function is called multiple times on the same \c ChangeFilePath + * object, only the last call will be taken into account. + * + * @param str The string to add. + * @return *this + */ + ChangeFilePath &addToBaseName(const QString &str) { + addToBaseNameStr = str; + return *this; + } + + /** + * Remove file extension. + * + * Examples: + * a.b.c -> a.b + * a. -> a + * .a -> + * a -> a + * + * @return *this + */ + ChangeFilePath &removeExtension() { + doRemoveExtension = true; + return *this; + } + + /** + * Add file extension. + * + * Add an extension to a file name. If the file name already has an extension, + * it won't be removed (unless \c removeExtension is set). + * + * If this function is called multiple times on the same \c ChangeFilePath + * object, only the last call will be taken into account. + * + * @param ext File extension to add. + * @return *this + */ + ChangeFilePath &addExtension(const QString &ext) { + addExtensionStr = ext; + return *this; + } + + /** + * Change file extension. + * + * Change file extension to a given string. If file has no extension, add one. + * Same as \c removeExtension + \c addExtension. + * + * @param ext New file extension. + * @return *this + */ + ChangeFilePath &setExtension(const QString &ext) { + return removeExtension().addExtension(ext); + } + + /** + * Remove language code from a file name. + * + * Remove language code from a file name if it has one. + * Examples: + * a.b.c -> a.b.c + * a.eng.c -> a.c + * eng.b.c -> eng.b.c + * a.eng -> a.eng + * + * \c removeLanguageCode can be combined with \c addLanguageCode. The order + * in which these two functions were called makes no diffrence, + * \c removeLanguageCode will cause removal of the language code that was + * present in original file name only. + * + * @return *this + */ + ChangeFilePath &removeLanguageCode() { + doRemoveLanguageCode = true; + return *this; + } + + /** + * Add language code to a file name. + * + * Add \c lang language code to a file name. If the file name already + * has a language code, it won't be removed (unless \c removeLanguageCode is + * set). If \a type is \c LCT_NONE, nothing will be added. + * + * Examples (add 'fra' code): + * a.b.c -> a.b.fra.c + * a.eng.c -> a.eng.fra.c + * + * Examples (add 'fra' code with \c removeLanguageCode also set): + * a.b.c -> a.b.fra.c + * a.eng.c -> a.fra.c + * + * If this function is called multiple times on the same \c ChangeFilePath + * object, only the last call will be taken into account. + * + * @param lang The language. + * @param type Type of the code to add. + * @return *this + */ + ChangeFilePath &addLanguageCode(const SubtitleLanguage &lang, + LangCodeType type) { + addLanguageCodeLang = lang; + addLanguageCodeType = type; + return *this; + } + + /** + * Apply changes on a given string. + * @param path File path to modify. + * @return Modified file path. + */ + QString apply(const QString &path) const; + + private: + QString addToBaseNameStr; + bool doRemoveExtension = false; + QString addExtensionStr; + bool doRemoveLanguageCode = false; + SubtitleLanguage addLanguageCodeLang; + LangCodeType addLanguageCodeType = LCT_NONE; +}; + +#endif // PATHUTILS_H + From cd88532775f9ddee307995691d2d1cd3008e0bf8 Mon Sep 17 00:00:00 2001 From: a-sum-duma Date: Tue, 26 Jul 2022 12:05:26 +0200 Subject: [PATCH 10/10] Support language codes in file names while converting subtitles --- gui/src/forms/frmconvert.cpp | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/gui/src/forms/frmconvert.cpp b/gui/src/forms/frmconvert.cpp index 690892c..1aee66a 100644 --- a/gui/src/forms/frmconvert.cpp +++ b/gui/src/forms/frmconvert.cpp @@ -16,6 +16,7 @@ #include "libqnapi.h" #include "movieinfo/movieinfoprovider.h" #include "qnapiopendialog.h" +#include "utils/pathutils.h" #include #include @@ -148,21 +149,35 @@ void frmConvert::checkFPSNeeded() { ui.pbMovieFPSSelect->setEnabled(fpsNeeded); if (fpsNeeded) { - QFileInfo srcSubFI(ui.leSrcSubFile->text()); - - QString movieFilePathBase = - srcSubFI.absoluteDir().filePath(srcSubFI.completeBaseName()); - - foreach (QString movieExt, staticConfig->movieExtensions()) { - QString movieFilePath = movieFilePathBase + "." + movieExt; - if (QFileInfo(movieFilePath).exists()) { - Maybe maybeFPS = determineMovieFPS(movieFilePath); - if (maybeFPS) { - ui.cbMovieFPS->setCurrentText(maybeFPS.value()); - ui.cbFPSTo->setCurrentText(maybeFPS.value()); + QString srcSubAbsoluteFilePath = + QFileInfo(ui.leSrcSubFile->text()).absoluteFilePath(); + + QString movieFilePathBase = ChangeFilePath() + .removeExtension().apply(srcSubAbsoluteFilePath); + + auto determineFPSFromPathBase = [this, &movieFilePathBase] () { + foreach (QString movieExt, staticConfig->movieExtensions()) { + QString movieFilePath = movieFilePathBase + "." + movieExt; + if (QFileInfo(movieFilePath).exists()) { + Maybe maybeFPS = determineMovieFPS(movieFilePath); + if (maybeFPS) { + ui.cbMovieFPS->setCurrentText(maybeFPS.value()); + ui.cbFPSTo->setCurrentText(maybeFPS.value()); + } + return true; } - break; } + return false; + }; + + if (determineFPSFromPathBase()) return; + + // try removing language code from file name + QString movieFilePathBaseWithoutLang = ChangeFilePath() + .removeExtension().removeLanguageCode().apply(srcSubAbsoluteFilePath); + if (movieFilePathBase != movieFilePathBaseWithoutLang) { + movieFilePathBase = movieFilePathBaseWithoutLang; + determineFPSFromPathBase(); } } }