mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-19 19:20:52 +00:00
Merge pull request #7832 from glassez/rss-import
Implement Import/Export RSS rules. Closes #7721
This commit is contained in:
commit
a7da714b13
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "rss_autodownloader.h"
|
#include "rss_autodownloader.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include "../bittorrent/magneturi.h"
|
#include "../bittorrent/magneturi.h"
|
||||||
#include "../bittorrent/session.h"
|
#include "../bittorrent/session.h"
|
||||||
@ -63,6 +65,32 @@ const QString RulesFileName(QStringLiteral("download_rules.json"));
|
|||||||
|
|
||||||
const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/AutoDownloader/EnableProcessing"));
|
const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/AutoDownloader/EnableProcessing"));
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QVector<RSS::AutoDownloadRule> rulesFromJSON(const QByteArray &jsonData)
|
||||||
|
{
|
||||||
|
QJsonParseError jsonError;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &jsonError);
|
||||||
|
if (jsonError.error != QJsonParseError::NoError)
|
||||||
|
throw RSS::ParsingError(jsonError.errorString());
|
||||||
|
|
||||||
|
if (!jsonDoc.isObject())
|
||||||
|
throw RSS::ParsingError(RSS::AutoDownloader::tr("Invalid data format."));
|
||||||
|
|
||||||
|
const QJsonObject jsonObj {jsonDoc.object()};
|
||||||
|
QVector<RSS::AutoDownloadRule> rules;
|
||||||
|
for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it) {
|
||||||
|
const QJsonValue jsonVal {it.value()};
|
||||||
|
if (!jsonVal.isObject())
|
||||||
|
throw RSS::ParsingError(RSS::AutoDownloader::tr("Invalid data format."));
|
||||||
|
|
||||||
|
rules.append(RSS::AutoDownloadRule::fromJsonObject(jsonVal.toObject(), it.key()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using namespace RSS;
|
using namespace RSS;
|
||||||
|
|
||||||
QPointer<AutoDownloader> AutoDownloader::m_instance = nullptr;
|
QPointer<AutoDownloader> AutoDownloader::m_instance = nullptr;
|
||||||
@ -84,8 +112,8 @@ AutoDownloader::AutoDownloader()
|
|||||||
connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater);
|
connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater);
|
||||||
connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
|
connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
|
||||||
{
|
{
|
||||||
Logger::instance()->addMessage(QString("Couldn't save RSS AutoDownloader data in %1. Error: %2")
|
LogMsg(tr("Couldn't save RSS AutoDownloader data in %1. Error: %2")
|
||||||
.arg(fileName).arg(errorString), Log::WARNING);
|
.arg(fileName).arg(errorString), Log::CRITICAL);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_ioThread->start();
|
m_ioThread->start();
|
||||||
@ -174,6 +202,70 @@ void AutoDownloader::removeRule(const QString &ruleName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRules(AutoDownloader::RulesFileFormat format) const
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case RulesFileFormat::Legacy:
|
||||||
|
return exportRulesToLegacyFormat();
|
||||||
|
default:
|
||||||
|
return exportRulesToJSONFormat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRules(const QByteArray &data, AutoDownloader::RulesFileFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case RulesFileFormat::Legacy:
|
||||||
|
importRulesFromLegacyFormat(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
importRulesFromJSONFormat(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRulesToJSONFormat() const
|
||||||
|
{
|
||||||
|
QJsonObject jsonObj;
|
||||||
|
for (const auto &rule : rules())
|
||||||
|
jsonObj.insert(rule.name(), rule.toJsonObject());
|
||||||
|
|
||||||
|
return QJsonDocument(jsonObj).toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRulesFromJSONFormat(const QByteArray &data)
|
||||||
|
{
|
||||||
|
const auto rules = rulesFromJSON(data);
|
||||||
|
for (const auto &rule : rules)
|
||||||
|
insertRule(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray AutoDownloader::exportRulesToLegacyFormat() const
|
||||||
|
{
|
||||||
|
QVariantHash dict;
|
||||||
|
for (const auto &rule : rules())
|
||||||
|
dict[rule.name()] = rule.toLegacyDict();
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
QDataStream out(&data, QIODevice::WriteOnly);
|
||||||
|
out.setVersion(QDataStream::Qt_4_5);
|
||||||
|
out << dict;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloader::importRulesFromLegacyFormat(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QDataStream in(data);
|
||||||
|
in.setVersion(QDataStream::Qt_4_5);
|
||||||
|
QVariantHash dict;
|
||||||
|
in >> dict;
|
||||||
|
if (in.status() != QDataStream::Ok)
|
||||||
|
throw ParsingError(tr("Invalid data format"));
|
||||||
|
|
||||||
|
for (const QVariant &val : dict)
|
||||||
|
insertRule(AutoDownloadRule::fromLegacyDict(val.toHash()));
|
||||||
|
}
|
||||||
|
|
||||||
void AutoDownloader::process()
|
void AutoDownloader::process()
|
||||||
{
|
{
|
||||||
if (m_processingQueue.isEmpty()) return; // processing was disabled
|
if (m_processingQueue.isEmpty()) return; // processing was disabled
|
||||||
@ -276,39 +368,20 @@ void AutoDownloader::load()
|
|||||||
else if (rulesFile.open(QFile::ReadOnly))
|
else if (rulesFile.open(QFile::ReadOnly))
|
||||||
loadRules(rulesFile.readAll());
|
loadRules(rulesFile.readAll());
|
||||||
else
|
else
|
||||||
Logger::instance()->addMessage(
|
LogMsg(tr("Couldn't read RSS AutoDownloader rules from %1. Error: %2")
|
||||||
QString("Couldn't read RSS AutoDownloader rules from %1. Error: %2")
|
.arg(rulesFile.fileName()).arg(rulesFile.errorString()), Log::CRITICAL);
|
||||||
.arg(rulesFile.fileName()).arg(rulesFile.errorString()), Log::WARNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoDownloader::loadRules(const QByteArray &data)
|
void AutoDownloader::loadRules(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QJsonParseError jsonError;
|
try {
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
const auto rules = rulesFromJSON(data);
|
||||||
if (jsonError.error != QJsonParseError::NoError) {
|
for (const auto &rule : rules)
|
||||||
Logger::instance()->addMessage(
|
setRule_impl(rule);
|
||||||
QString("Couldn't parse RSS AutoDownloader rules. Error: %1")
|
|
||||||
.arg(jsonError.errorString()), Log::WARNING);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
catch (const ParsingError &error) {
|
||||||
if (!jsonDoc.isObject()) {
|
LogMsg(tr("Couldn't load RSS AutoDownloader rules. Reason: %1")
|
||||||
Logger::instance()->addMessage(
|
.arg(error.message()), Log::CRITICAL);
|
||||||
QString("Couldn't load RSS AutoDownloader rules. Invalid data format."), Log::WARNING);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject jsonObj = jsonDoc.object();
|
|
||||||
foreach (const QString &key, jsonObj.keys()) {
|
|
||||||
const QJsonValue jsonVal = jsonObj.value(key);
|
|
||||||
if (!jsonVal.isObject()) {
|
|
||||||
Logger::instance()->addMessage(
|
|
||||||
QString("Couldn't load RSS AutoDownloader rule '%1'. Invalid data format.")
|
|
||||||
.arg(key), Log::WARNING);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRule_impl(AutoDownloadRule::fromJsonObject(jsonVal.toObject(), key));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +390,7 @@ void AutoDownloader::loadRulesLegacy()
|
|||||||
SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss"));
|
SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss"));
|
||||||
QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash();
|
QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash();
|
||||||
foreach (const QVariant &ruleVar, rules) {
|
foreach (const QVariant &ruleVar, rules) {
|
||||||
auto rule = AutoDownloadRule::fromVariantHash(ruleVar.toHash());
|
auto rule = AutoDownloadRule::fromLegacyDict(ruleVar.toHash());
|
||||||
if (!rule.name().isEmpty())
|
if (!rule.name().isEmpty())
|
||||||
insertRule(rule);
|
insertRule(rule);
|
||||||
}
|
}
|
||||||
@ -385,3 +458,13 @@ void AutoDownloader::timerEvent(QTimerEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
store();
|
store();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsingError::ParsingError(const QString &message)
|
||||||
|
: std::runtime_error(message.toUtf8().data())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ParsingError::message() const
|
||||||
|
{
|
||||||
|
return what();
|
||||||
|
}
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
@ -49,6 +51,13 @@ namespace RSS
|
|||||||
|
|
||||||
class AutoDownloadRule;
|
class AutoDownloadRule;
|
||||||
|
|
||||||
|
class ParsingError : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ParsingError(const QString &message);
|
||||||
|
QString message() const;
|
||||||
|
};
|
||||||
|
|
||||||
class AutoDownloader final: public QObject
|
class AutoDownloader final: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -60,6 +69,12 @@ namespace RSS
|
|||||||
~AutoDownloader() override;
|
~AutoDownloader() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum class RulesFileFormat
|
||||||
|
{
|
||||||
|
Legacy,
|
||||||
|
JSON
|
||||||
|
};
|
||||||
|
|
||||||
static AutoDownloader *instance();
|
static AutoDownloader *instance();
|
||||||
|
|
||||||
bool isProcessingEnabled() const;
|
bool isProcessingEnabled() const;
|
||||||
@ -73,6 +88,9 @@ namespace RSS
|
|||||||
bool renameRule(const QString &ruleName, const QString &newRuleName);
|
bool renameRule(const QString &ruleName, const QString &newRuleName);
|
||||||
void removeRule(const QString &ruleName);
|
void removeRule(const QString &ruleName);
|
||||||
|
|
||||||
|
QByteArray exportRules(RulesFileFormat format = RulesFileFormat::JSON) const;
|
||||||
|
void importRules(const QByteArray &data, RulesFileFormat format = RulesFileFormat::JSON);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void processingStateChanged(bool enabled);
|
void processingStateChanged(bool enabled);
|
||||||
void ruleAdded(const QString &ruleName);
|
void ruleAdded(const QString &ruleName);
|
||||||
@ -98,6 +116,10 @@ namespace RSS
|
|||||||
void loadRulesLegacy();
|
void loadRulesLegacy();
|
||||||
void store();
|
void store();
|
||||||
void storeDeferred();
|
void storeDeferred();
|
||||||
|
QByteArray exportRulesToJSONFormat() const;
|
||||||
|
void importRulesFromJSONFormat(const QByteArray &data);
|
||||||
|
QByteArray exportRulesToLegacyFormat() const;
|
||||||
|
void importRulesFromLegacyFormat(const QByteArray &data);
|
||||||
|
|
||||||
static QPointer<AutoDownloader> m_instance;
|
static QPointer<AutoDownloader> m_instance;
|
||||||
|
|
||||||
|
@ -63,11 +63,29 @@ namespace
|
|||||||
QJsonValue triStateBoolToJsonValue(const TriStateBool &triStateBool)
|
QJsonValue triStateBoolToJsonValue(const TriStateBool &triStateBool)
|
||||||
{
|
{
|
||||||
switch (static_cast<int>(triStateBool)) {
|
switch (static_cast<int>(triStateBool)) {
|
||||||
case 0: return false; break;
|
case 0: return false;
|
||||||
case 1: return true; break;
|
case 1: return true;
|
||||||
default: return QJsonValue();
|
default: return QJsonValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TriStateBool addPausedLegacyToTriStateBool(int val)
|
||||||
|
{
|
||||||
|
switch (val) {
|
||||||
|
case 1: return TriStateBool::True; // always
|
||||||
|
case 2: return TriStateBool::False; // never
|
||||||
|
default: return TriStateBool::Undefined; // default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int triStateBoolToAddPausedLegacy(const TriStateBool &triStateBool)
|
||||||
|
{
|
||||||
|
switch (static_cast<int>(triStateBool)) {
|
||||||
|
case 0: return 2; // never
|
||||||
|
case 1: return 1; // always
|
||||||
|
default: return 0; // default
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString Str_Name(QStringLiteral("name"));
|
const QString Str_Name(QStringLiteral("name"));
|
||||||
@ -378,21 +396,37 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
|
|||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoDownloadRule AutoDownloadRule::fromVariantHash(const QVariantHash &varHash)
|
QVariantHash AutoDownloadRule::toLegacyDict() const
|
||||||
{
|
{
|
||||||
AutoDownloadRule rule(varHash.value("name").toString());
|
return {{"name", name()},
|
||||||
|
{"must_contain", mustContain()},
|
||||||
|
{"must_not_contain", mustNotContain()},
|
||||||
|
{"save_path", savePath()},
|
||||||
|
{"affected_feeds", feedURLs()},
|
||||||
|
{"enabled", isEnabled()},
|
||||||
|
{"category_assigned", assignedCategory()},
|
||||||
|
{"use_regex", useRegex()},
|
||||||
|
{"add_paused", triStateBoolToAddPausedLegacy(addPaused())},
|
||||||
|
{"episode_filter", episodeFilter()},
|
||||||
|
{"last_match", lastMatch()},
|
||||||
|
{"ignore_days", ignoreDays()}};
|
||||||
|
}
|
||||||
|
|
||||||
rule.setUseRegex(varHash.value("use_regex", false).toBool());
|
AutoDownloadRule AutoDownloadRule::fromLegacyDict(const QVariantHash &dict)
|
||||||
rule.setMustContain(varHash.value("must_contain").toString());
|
{
|
||||||
rule.setMustNotContain(varHash.value("must_not_contain").toString());
|
AutoDownloadRule rule(dict.value("name").toString());
|
||||||
rule.setEpisodeFilter(varHash.value("episode_filter").toString());
|
|
||||||
rule.setFeedURLs(varHash.value("affected_feeds").toStringList());
|
rule.setUseRegex(dict.value("use_regex", false).toBool());
|
||||||
rule.setEnabled(varHash.value("enabled", false).toBool());
|
rule.setMustContain(dict.value("must_contain").toString());
|
||||||
rule.setSavePath(varHash.value("save_path").toString());
|
rule.setMustNotContain(dict.value("must_not_contain").toString());
|
||||||
rule.setCategory(varHash.value("category_assigned").toString());
|
rule.setEpisodeFilter(dict.value("episode_filter").toString());
|
||||||
rule.setAddPaused(TriStateBool(varHash.value("add_paused").toInt() - 1));
|
rule.setFeedURLs(dict.value("affected_feeds").toStringList());
|
||||||
rule.setLastMatch(varHash.value("last_match").toDateTime());
|
rule.setEnabled(dict.value("enabled", false).toBool());
|
||||||
rule.setIgnoreDays(varHash.value("ignore_days").toInt());
|
rule.setSavePath(dict.value("save_path").toString());
|
||||||
|
rule.setCategory(dict.value("category_assigned").toString());
|
||||||
|
rule.setAddPaused(addPausedLegacyToTriStateBool(dict.value("add_paused").toInt()));
|
||||||
|
rule.setLastMatch(dict.value("last_match").toDateTime());
|
||||||
|
rule.setIgnoreDays(dict.value("ignore_days").toInt());
|
||||||
|
|
||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,9 @@ namespace RSS
|
|||||||
|
|
||||||
QJsonObject toJsonObject() const;
|
QJsonObject toJsonObject() const;
|
||||||
static AutoDownloadRule fromJsonObject(const QJsonObject &jsonObj, const QString &name = "");
|
static AutoDownloadRule fromJsonObject(const QJsonObject &jsonObj, const QString &name = "");
|
||||||
static AutoDownloadRule fromVariantHash(const QVariantHash &varHash);
|
|
||||||
|
QVariantHash toLegacyDict() const;
|
||||||
|
static AutoDownloadRule fromLegacyDict(const QVariantHash &dict);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool matches(const QString &articleTitle, const QString &expression) const;
|
bool matches(const QString &articleTitle, const QString &expression) const;
|
||||||
|
@ -54,8 +54,13 @@
|
|||||||
#include "autoexpandabledialog.h"
|
#include "autoexpandabledialog.h"
|
||||||
#include "ui_automatedrssdownloader.h"
|
#include "ui_automatedrssdownloader.h"
|
||||||
|
|
||||||
|
const QString EXT_JSON {QStringLiteral(".json")};
|
||||||
|
const QString EXT_LEGACY {QStringLiteral(".rssrules")};
|
||||||
|
|
||||||
AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
|
AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
|
, m_formatFilterJSON(QString("%1 (*%2)").arg(tr("Rules")).arg(EXT_JSON))
|
||||||
|
, m_formatFilterLegacy(QString("%1 (*%2)").arg(tr("Rules (legacy)")).arg(EXT_LEGACY))
|
||||||
, m_ui(new Ui::AutomatedRssDownloader)
|
, m_ui(new Ui::AutomatedRssDownloader)
|
||||||
, m_currentRuleItem(nullptr)
|
, m_currentRuleItem(nullptr)
|
||||||
{
|
{
|
||||||
@ -384,31 +389,73 @@ void AutomatedRssDownloader::on_browseSP_clicked()
|
|||||||
|
|
||||||
void AutomatedRssDownloader::on_exportBtn_clicked()
|
void AutomatedRssDownloader::on_exportBtn_clicked()
|
||||||
{
|
{
|
||||||
// if (m_editableRuleList->isEmpty()) {
|
if (RSS::AutoDownloader::instance()->rules().isEmpty()) {
|
||||||
// QMessageBox::warning(this, tr("Invalid action"), tr("The list is empty, there is nothing to export."));
|
QMessageBox::warning(this, tr("Invalid action")
|
||||||
// return;
|
, tr("The list is empty, there is nothing to export."));
|
||||||
// }
|
return;
|
||||||
// // Ask for a save path
|
}
|
||||||
// QString save_path = QFileDialog::getSaveFileName(this, tr("Where would you like to save the list?"), QDir::homePath(), tr("Rules list (*.rssrules)"));
|
|
||||||
// if (save_path.isEmpty()) return;
|
QString selectedFilter {m_formatFilterJSON};
|
||||||
// if (!save_path.endsWith(".rssrules", Qt::CaseInsensitive))
|
QString path = QFileDialog::getSaveFileName(
|
||||||
// save_path += ".rssrules";
|
this, tr("Export RSS rules"), QDir::homePath()
|
||||||
// if (!m_editableRuleList->serialize(save_path)) {
|
, QString("%1;;%2").arg(m_formatFilterJSON).arg(m_formatFilterLegacy), &selectedFilter);
|
||||||
// QMessageBox::warning(this, tr("I/O Error"), tr("Failed to create the destination file"));
|
if (path.isEmpty()) return;
|
||||||
// return;
|
|
||||||
// }
|
const RSS::AutoDownloader::RulesFileFormat format {
|
||||||
|
(selectedFilter == m_formatFilterJSON)
|
||||||
|
? RSS::AutoDownloader::RulesFileFormat::JSON
|
||||||
|
: RSS::AutoDownloader::RulesFileFormat::Legacy
|
||||||
|
};
|
||||||
|
|
||||||
|
if (format == RSS::AutoDownloader::RulesFileFormat::JSON) {
|
||||||
|
if (!path.endsWith(EXT_JSON, Qt::CaseInsensitive))
|
||||||
|
path += EXT_JSON;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!path.endsWith(EXT_LEGACY, Qt::CaseInsensitive))
|
||||||
|
path += EXT_LEGACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file {path};
|
||||||
|
if (!file.open(QFile::WriteOnly)
|
||||||
|
|| (file.write(RSS::AutoDownloader::instance()->exportRules(format)) == -1)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("I/O Error")
|
||||||
|
, tr("Failed to create the destination file. Reason: %1").arg(file.errorString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutomatedRssDownloader::on_importBtn_clicked()
|
void AutomatedRssDownloader::on_importBtn_clicked()
|
||||||
{
|
{
|
||||||
// // Ask for filter path
|
QString selectedFilter {m_formatFilterJSON};
|
||||||
// QString load_path = QFileDialog::getOpenFileName(this, tr("Please point to the RSS download rules file"), QDir::homePath(), tr("Rules list") + QString(" (*.rssrules *.filters)"));
|
QString path = QFileDialog::getOpenFileName(
|
||||||
// if (load_path.isEmpty() || !QFile::exists(load_path)) return;
|
this, tr("Import RSS rules"), QDir::homePath()
|
||||||
// // Load it
|
, QString("%1;;%2").arg(m_formatFilterJSON).arg(m_formatFilterLegacy), &selectedFilter);
|
||||||
// if (!m_editableRuleList->unserialize(load_path)) {
|
if (path.isEmpty() || !QFile::exists(path))
|
||||||
// QMessageBox::warning(this, tr("Import Error"), tr("Failed to import the selected rules file"));
|
return;
|
||||||
// return;
|
|
||||||
// }
|
QFile file {path};
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("I/O Error")
|
||||||
|
, tr("Failed to open the file. Reason: %1").arg(file.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RSS::AutoDownloader::RulesFileFormat format {
|
||||||
|
(selectedFilter == m_formatFilterJSON)
|
||||||
|
? RSS::AutoDownloader::RulesFileFormat::JSON
|
||||||
|
: RSS::AutoDownloader::RulesFileFormat::Legacy
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
RSS::AutoDownloader::instance()->importRules(file.readAll(),format);
|
||||||
|
}
|
||||||
|
catch (const RSS::ParsingError &error) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("Import Error")
|
||||||
|
, tr("Failed to import the selected rules file. Reason: %1").arg(error.message()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutomatedRssDownloader::displayRulesListMenu()
|
void AutomatedRssDownloader::displayRulesListMenu()
|
||||||
|
@ -96,6 +96,9 @@ private:
|
|||||||
void updateFeedList();
|
void updateFeedList();
|
||||||
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);
|
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);
|
||||||
|
|
||||||
|
const QString m_formatFilterJSON;
|
||||||
|
const QString m_formatFilterLegacy;
|
||||||
|
|
||||||
Ui::AutomatedRssDownloader *m_ui;
|
Ui::AutomatedRssDownloader *m_ui;
|
||||||
QListWidgetItem *m_currentRuleItem;
|
QListWidgetItem *m_currentRuleItem;
|
||||||
QShortcut *m_editHotkey;
|
QShortcut *m_editHotkey;
|
||||||
|
@ -386,7 +386,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="importBtn">
|
<widget class="QPushButton" name="importBtn">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Import...</string>
|
<string>&Import...</string>
|
||||||
@ -396,7 +396,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="exportBtn">
|
<widget class="QPushButton" name="exportBtn">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Export...</string>
|
<string>&Export...</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user