diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 6898346ec..2403c2e11 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -110,6 +110,7 @@ add_library(qbt_base STATIC applicationcomponent.cpp asyncfilestorage.cpp bittorrent/abstractfilestorage.cpp + bittorrent/addtorrentparams.cpp bittorrent/bandwidthscheduler.cpp bittorrent/bencoderesumedatastorage.cpp bittorrent/categoryoptions.cpp diff --git a/src/base/base.pri b/src/base/base.pri index 7686090b3..e6fd1ca3b 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -110,6 +110,7 @@ SOURCES += \ $$PWD/applicationcomponent.cpp \ $$PWD/asyncfilestorage.cpp \ $$PWD/bittorrent/abstractfilestorage.cpp \ + $$PWD/bittorrent/addtorrentparams.cpp \ $$PWD/bittorrent/bandwidthscheduler.cpp \ $$PWD/bittorrent/bencoderesumedatastorage.cpp \ $$PWD/bittorrent/categoryoptions.cpp \ diff --git a/src/base/bittorrent/addtorrentparams.cpp b/src/base/bittorrent/addtorrentparams.cpp new file mode 100644 index 000000000..cdbed3435 --- /dev/null +++ b/src/base/bittorrent/addtorrentparams.cpp @@ -0,0 +1,150 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2015-2023 Vladimir Golovnev + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "addtorrentparams.h" + +#include +#include +#include + +#include "base/utils/string.h" + +const QString PARAM_CATEGORY = u"category"_qs; +const QString PARAM_TAGS = u"tags"_qs; +const QString PARAM_SAVEPATH = u"save_path"_qs; +const QString PARAM_USEDOWNLOADPATH = u"use_download_path"_qs; +const QString PARAM_DOWNLOADPATH = u"download_path"_qs; +const QString PARAM_OPERATINGMODE = u"operating_mode"_qs; +const QString PARAM_QUEUETOP = u"add_to_top_of_queue"_qs; +const QString PARAM_STOPPED = u"stopped"_qs; +const QString PARAM_SKIPCHECKING = u"skip_checking"_qs; +const QString PARAM_CONTENTLAYOUT = u"content_layout"_qs; +const QString PARAM_AUTOTMM = u"use_auto_tmm"_qs; +const QString PARAM_UPLOADLIMIT = u"upload_limit"_qs; +const QString PARAM_DOWNLOADLIMIT = u"download_limit"_qs; +const QString PARAM_SEEDINGTIMELIMIT = u"seeding_time_limit"_qs; +const QString PARAM_RATIOLIMIT = u"ratio_limit"_qs; + +namespace +{ + TagSet parseTagSet(const QJsonArray &jsonArr) + { + TagSet tags; + for (const QJsonValue &jsonVal : jsonArr) + tags.insert(jsonVal.toString()); + + return tags; + } + + QJsonArray serializeTagSet(const TagSet &tags) + { + QJsonArray arr; + for (const QString &tag : tags) + arr.append(tag); + + return arr; + } + + std::optional getOptionalBool(const QJsonObject &jsonObj, const QString &key) + { + const QJsonValue jsonVal = jsonObj.value(key); + if (jsonVal.isUndefined() || jsonVal.isNull()) + return std::nullopt; + + return jsonVal.toBool(); + } + + template + std::optional getOptionalEnum(const QJsonObject &jsonObj, const QString &key) + { + const QJsonValue jsonVal = jsonObj.value(key); + if (jsonVal.isUndefined() || jsonVal.isNull()) + return std::nullopt; + + return Utils::String::toEnum(jsonVal.toString(), {}); + } + + template + Enum getEnum(const QJsonObject &jsonObj, const QString &key) + { + const QJsonValue jsonVal = jsonObj.value(key); + return Utils::String::toEnum(jsonVal.toString(), {}); + } +} + +BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject &jsonObj) +{ + AddTorrentParams params; + params.category = jsonObj.value(PARAM_CATEGORY).toString(); + params.tags = parseTagSet(jsonObj.value(PARAM_TAGS).toArray()); + params.savePath = Path(jsonObj.value(PARAM_SAVEPATH).toString()); + params.useDownloadPath = getOptionalBool(jsonObj, PARAM_USEDOWNLOADPATH); + params.downloadPath = Path(jsonObj.value(PARAM_DOWNLOADPATH).toString()); + params.addForced = (getEnum(jsonObj, PARAM_OPERATINGMODE) == BitTorrent::TorrentOperatingMode::Forced); + params.addToQueueTop = getOptionalBool(jsonObj, PARAM_QUEUETOP); + params.addPaused = getOptionalBool(jsonObj, PARAM_STOPPED); + params.skipChecking = jsonObj.value(PARAM_SKIPCHECKING).toBool(); + params.contentLayout = getOptionalEnum(jsonObj, PARAM_CONTENTLAYOUT); + params.useAutoTMM = getOptionalBool(jsonObj, PARAM_AUTOTMM); + params.uploadLimit = jsonObj.value(PARAM_UPLOADLIMIT).toInt(-1); + params.downloadLimit = jsonObj.value(PARAM_DOWNLOADLIMIT).toInt(-1); + params.seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME); + params.ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(BitTorrent::Torrent::USE_GLOBAL_RATIO); + + return params; +} + +QJsonObject BitTorrent::serializeAddTorrentParams(const AddTorrentParams ¶ms) +{ + QJsonObject jsonObj { + {PARAM_CATEGORY, params.category}, + {PARAM_TAGS, serializeTagSet(params.tags)}, + {PARAM_SAVEPATH, params.savePath.data()}, + {PARAM_DOWNLOADPATH, params.downloadPath.data()}, + {PARAM_OPERATINGMODE, Utils::String::fromEnum(params.addForced + ? BitTorrent::TorrentOperatingMode::Forced : BitTorrent::TorrentOperatingMode::AutoManaged)}, + {PARAM_SKIPCHECKING, params.skipChecking}, + {PARAM_UPLOADLIMIT, params.uploadLimit}, + {PARAM_DOWNLOADLIMIT, params.downloadLimit}, + {PARAM_SEEDINGTIMELIMIT, params.seedingTimeLimit}, + {PARAM_RATIOLIMIT, params.ratioLimit} + }; + + if (params.addToQueueTop) + jsonObj[PARAM_QUEUETOP] = *params.addToQueueTop; + if (params.addPaused) + jsonObj[PARAM_STOPPED] = *params.addPaused; + if (params.contentLayout) + jsonObj[PARAM_CONTENTLAYOUT] = Utils::String::fromEnum(*params.contentLayout); + if (params.useAutoTMM) + jsonObj[PARAM_AUTOTMM] = *params.useAutoTMM; + if (params.useDownloadPath) + jsonObj[PARAM_USEDOWNLOADPATH] = *params.useDownloadPath; + + return jsonObj; +} diff --git a/src/base/bittorrent/addtorrentparams.h b/src/base/bittorrent/addtorrentparams.h index 6039df669..64f8d3eb7 100644 --- a/src/base/bittorrent/addtorrentparams.h +++ b/src/base/bittorrent/addtorrentparams.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev + * Copyright (C) 2015-2023 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -39,6 +39,8 @@ #include "torrent.h" #include "torrentcontentlayout.h" +class QJsonObject; + namespace BitTorrent { enum class DownloadPriority; @@ -67,6 +69,9 @@ namespace BitTorrent int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME; qreal ratioLimit = Torrent::USE_GLOBAL_RATIO; }; + + AddTorrentParams parseAddTorrentParams(const QJsonObject &jsonObj); + QJsonObject serializeAddTorrentParams(const AddTorrentParams ¶ms); } Q_DECLARE_METATYPE(BitTorrent::AddTorrentParams) diff --git a/src/base/torrentfileswatcher.cpp b/src/base/torrentfileswatcher.cpp index d47ea5742..37262d165 100644 --- a/src/base/torrentfileswatcher.cpp +++ b/src/base/torrentfileswatcher.cpp @@ -36,10 +36,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -70,124 +68,12 @@ const QString CONF_FILE_NAME = u"watched_folders.json"_qs; const QString OPTION_ADDTORRENTPARAMS = u"add_torrent_params"_qs; const QString OPTION_RECURSIVE = u"recursive"_qs; -const QString PARAM_CATEGORY = u"category"_qs; -const QString PARAM_TAGS = u"tags"_qs; -const QString PARAM_SAVEPATH = u"save_path"_qs; -const QString PARAM_USEDOWNLOADPATH = u"use_download_path"_qs; -const QString PARAM_DOWNLOADPATH = u"download_path"_qs; -const QString PARAM_OPERATINGMODE = u"operating_mode"_qs; -const QString PARAM_QUEUETOP = u"add_to_top_of_queue"_qs; -const QString PARAM_STOPPED = u"stopped"_qs; -const QString PARAM_SKIPCHECKING = u"skip_checking"_qs; -const QString PARAM_CONTENTLAYOUT = u"content_layout"_qs; -const QString PARAM_AUTOTMM = u"use_auto_tmm"_qs; -const QString PARAM_UPLOADLIMIT = u"upload_limit"_qs; -const QString PARAM_DOWNLOADLIMIT = u"download_limit"_qs; -const QString PARAM_SEEDINGTIMELIMIT = u"seeding_time_limit"_qs; -const QString PARAM_RATIOLIMIT = u"ratio_limit"_qs; - namespace { - TagSet parseTagSet(const QJsonArray &jsonArr) - { - TagSet tags; - for (const QJsonValue &jsonVal : jsonArr) - tags.insert(jsonVal.toString()); - - return tags; - } - - QJsonArray serializeTagSet(const TagSet &tags) - { - QJsonArray arr; - for (const QString &tag : tags) - arr.append(tag); - - return arr; - } - - std::optional getOptionalBool(const QJsonObject &jsonObj, const QString &key) - { - const QJsonValue jsonVal = jsonObj.value(key); - if (jsonVal.isUndefined() || jsonVal.isNull()) - return std::nullopt; - - return jsonVal.toBool(); - } - - template - std::optional getOptionalEnum(const QJsonObject &jsonObj, const QString &key) - { - const QJsonValue jsonVal = jsonObj.value(key); - if (jsonVal.isUndefined() || jsonVal.isNull()) - return std::nullopt; - - return Utils::String::toEnum(jsonVal.toString(), {}); - } - - template - Enum getEnum(const QJsonObject &jsonObj, const QString &key) - { - const QJsonValue jsonVal = jsonObj.value(key); - return Utils::String::toEnum(jsonVal.toString(), {}); - } - - BitTorrent::AddTorrentParams parseAddTorrentParams(const QJsonObject &jsonObj) - { - BitTorrent::AddTorrentParams params; - params.category = jsonObj.value(PARAM_CATEGORY).toString(); - params.tags = parseTagSet(jsonObj.value(PARAM_TAGS).toArray()); - params.savePath = Path(jsonObj.value(PARAM_SAVEPATH).toString()); - params.useDownloadPath = getOptionalBool(jsonObj, PARAM_USEDOWNLOADPATH); - params.downloadPath = Path(jsonObj.value(PARAM_DOWNLOADPATH).toString()); - params.addForced = (getEnum(jsonObj, PARAM_OPERATINGMODE) == BitTorrent::TorrentOperatingMode::Forced); - params.addToQueueTop = getOptionalBool(jsonObj, PARAM_QUEUETOP); - params.addPaused = getOptionalBool(jsonObj, PARAM_STOPPED); - params.skipChecking = jsonObj.value(PARAM_SKIPCHECKING).toBool(); - params.contentLayout = getOptionalEnum(jsonObj, PARAM_CONTENTLAYOUT); - params.useAutoTMM = getOptionalBool(jsonObj, PARAM_AUTOTMM); - params.uploadLimit = jsonObj.value(PARAM_UPLOADLIMIT).toInt(-1); - params.downloadLimit = jsonObj.value(PARAM_DOWNLOADLIMIT).toInt(-1); - params.seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME); - params.ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(BitTorrent::Torrent::USE_GLOBAL_RATIO); - - return params; - } - - QJsonObject serializeAddTorrentParams(const BitTorrent::AddTorrentParams ¶ms) - { - QJsonObject jsonObj { - {PARAM_CATEGORY, params.category}, - {PARAM_TAGS, serializeTagSet(params.tags)}, - {PARAM_SAVEPATH, params.savePath.data()}, - {PARAM_DOWNLOADPATH, params.downloadPath.data()}, - {PARAM_OPERATINGMODE, Utils::String::fromEnum(params.addForced - ? BitTorrent::TorrentOperatingMode::Forced : BitTorrent::TorrentOperatingMode::AutoManaged)}, - {PARAM_SKIPCHECKING, params.skipChecking}, - {PARAM_UPLOADLIMIT, params.uploadLimit}, - {PARAM_DOWNLOADLIMIT, params.downloadLimit}, - {PARAM_SEEDINGTIMELIMIT, params.seedingTimeLimit}, - {PARAM_RATIOLIMIT, params.ratioLimit} - }; - - if (params.addToQueueTop) - jsonObj[PARAM_QUEUETOP] = *params.addToQueueTop; - if (params.addPaused) - jsonObj[PARAM_STOPPED] = *params.addPaused; - if (params.contentLayout) - jsonObj[PARAM_CONTENTLAYOUT] = Utils::String::fromEnum(*params.contentLayout); - if (params.useAutoTMM) - jsonObj[PARAM_AUTOTMM] = *params.useAutoTMM; - if (params.useDownloadPath) - jsonObj[PARAM_USEDOWNLOADPATH] = *params.useDownloadPath; - - return jsonObj; - } - TorrentFilesWatcher::WatchedFolderOptions parseWatchedFolderOptions(const QJsonObject &jsonObj) { TorrentFilesWatcher::WatchedFolderOptions options; - options.addTorrentParams = parseAddTorrentParams(jsonObj.value(OPTION_ADDTORRENTPARAMS).toObject()); + options.addTorrentParams = BitTorrent::parseAddTorrentParams(jsonObj.value(OPTION_ADDTORRENTPARAMS).toObject()); options.recursive = jsonObj.value(OPTION_RECURSIVE).toBool(); return options; @@ -195,10 +81,8 @@ namespace QJsonObject serializeWatchedFolderOptions(const TorrentFilesWatcher::WatchedFolderOptions &options) { - return { - {OPTION_ADDTORRENTPARAMS, serializeAddTorrentParams(options.addTorrentParams)}, - {OPTION_RECURSIVE, options.recursive} - }; + return {{OPTION_ADDTORRENTPARAMS, BitTorrent::serializeAddTorrentParams(options.addTorrentParams)}, + {OPTION_RECURSIVE, options.recursive}}; } }