Browse Source

Merge pull request #15536 from glassez/expected

Don't use output parameters for error handling
adaptive-webui-19844
Vladimir Golovnev 3 years ago committed by GitHub
parent
commit
5d5b0d572e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/base/bittorrent/session.cpp
  2. 55
      src/base/bittorrent/torrentinfo.cpp
  3. 7
      src/base/bittorrent/torrentinfo.h
  4. 96
      src/base/rss/rss_session.cpp
  5. 15
      src/base/rss/rss_session.h
  6. 12
      src/base/torrentfileswatcher.cpp
  7. 52
      src/gui/addnewtorrentdialog.cpp
  8. 2
      src/gui/addnewtorrentdialog.h
  9. 18
      src/gui/rss/rsswidget.cpp
  10. 6
      src/gui/torrentcreatordialog.cpp
  11. 24
      src/webui/api/rsscontroller.cpp
  12. 6
      src/webui/api/torrentscontroller.cpp

19
src/base/bittorrent/session.cpp

@ -69,7 +69,6 @@
#include <QUuid> #include <QUuid>
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/exceptions.h"
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
@ -1698,7 +1697,7 @@ void Session::handleDownloadFinished(const Net::DownloadResult &result)
{ {
case Net::DownloadStatus::Success: case Net::DownloadStatus::Success:
emit downloadFromUrlFinished(result.url); emit downloadFromUrlFinished(result.url);
addTorrent(TorrentInfo::load(result.data), m_downloadedTorrents.take(result.url)); addTorrent(TorrentInfo::load(result.data).value_or(TorrentInfo()), m_downloadedTorrents.take(result.url));
break; break;
case Net::DownloadStatus::RedirectedToMagnet: case Net::DownloadStatus::RedirectedToMagnet:
emit downloadFromUrlFinished(result.url); emit downloadFromUrlFinished(result.url);
@ -2028,7 +2027,7 @@ bool Session::addTorrent(const QString &source, const AddTorrentParams &params)
return addTorrent(magnetUri, params); return addTorrent(magnetUri, params);
TorrentFileGuard guard {source}; TorrentFileGuard guard {source};
if (addTorrent(TorrentInfo::loadFromFile(source), params)) if (addTorrent(TorrentInfo::loadFromFile(source).value_or(TorrentInfo()), params))
{ {
guard.markAsAddedToSession(); guard.markAsAddedToSession();
return true; return true;
@ -2317,14 +2316,11 @@ void Session::exportTorrentFile(const TorrentInfo &torrentInfo, const QString &f
newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename); newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename);
} }
try const nonstd::expected<void, QString> result = torrentInfo.saveToFile(newTorrentPath);
{ if (!result)
torrentInfo.saveToFile(newTorrentPath);
}
catch (const RuntimeError &err)
{ {
LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.") LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.")
.arg(newTorrentPath, err.message()), Log::WARNING); .arg(newTorrentPath, result.error()), Log::WARNING);
} }
} }
} }
@ -3938,8 +3934,7 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent)
qDebug("Found possible recursive torrent download."); qDebug("Found possible recursive torrent download.");
const QString torrentFullpath = torrent->savePath(true) + '/' + torrentRelpath; const QString torrentFullpath = torrent->savePath(true) + '/' + torrentRelpath;
qDebug("Full subtorrent path is %s", qUtf8Printable(torrentFullpath)); qDebug("Full subtorrent path is %s", qUtf8Printable(torrentFullpath));
TorrentInfo torrentInfo = TorrentInfo::loadFromFile(torrentFullpath); if (TorrentInfo::loadFromFile(torrentFullpath))
if (torrentInfo.isValid())
{ {
qDebug("emitting recursiveTorrentDownloadPossible()"); qDebug("emitting recursiveTorrentDownloadPossible()");
emit recursiveTorrentDownloadPossible(torrent); emit recursiveTorrentDownloadPossible(torrent);
@ -4167,7 +4162,7 @@ void Session::recursiveTorrentDownload(const TorrentID &id)
AddTorrentParams params; AddTorrentParams params;
// Passing the save path along to the sub torrent file // Passing the save path along to the sub torrent file
params.savePath = torrent->savePath(); params.savePath = torrent->savePath();
addTorrent(TorrentInfo::loadFromFile(torrentFullpath), params); addTorrent(TorrentInfo::loadFromFile(torrentFullpath).value_or(TorrentInfo()), params);
} }
} }
} }

55
src/base/bittorrent/torrentinfo.cpp

@ -40,7 +40,6 @@
#include <QUrl> #include <QUrl>
#include <QVector> #include <QVector>
#include "base/exceptions.h"
#include "base/global.h" #include "base/global.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
#include "base/utils/io.h" #include "base/utils/io.h"
@ -106,7 +105,7 @@ TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
return *this; return *this;
} }
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept nonstd::expected<TorrentInfo, QString> TorrentInfo::load(const QByteArray &data) noexcept
{ {
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are // 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
// used in `torrent_info()` constructor // used in `torrent_info()` constructor
@ -117,42 +116,23 @@ TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
const lt::bdecode_node node = lt::bdecode(data, ec const lt::bdecode_node node = lt::bdecode(data, ec
, nullptr, depthLimit, tokenLimit); , nullptr, depthLimit, tokenLimit);
if (ec) if (ec)
{ return nonstd::make_unexpected(QString::fromStdString(ec.message()));
if (error)
*error = QString::fromStdString(ec.message());
return TorrentInfo();
}
TorrentInfo info {std::shared_ptr<lt::torrent_info>(new lt::torrent_info(node, ec))}; TorrentInfo info {std::shared_ptr<lt::torrent_info>(new lt::torrent_info(node, ec))};
if (ec) if (ec)
{ return nonstd::make_unexpected(QString::fromStdString(ec.message()));
if (error)
*error = QString::fromStdString(ec.message());
return TorrentInfo();
}
return info; return info;
} }
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept nonstd::expected<TorrentInfo, QString> TorrentInfo::loadFromFile(const QString &path) noexcept
{ {
if (error)
error->clear();
QFile file {path}; QFile file {path};
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
{ return nonstd::make_unexpected(file.errorString());
if (error)
*error = file.errorString();
return TorrentInfo();
}
if (file.size() > MAX_TORRENT_SIZE) if (file.size() > MAX_TORRENT_SIZE)
{ return nonstd::make_unexpected(tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE)));
if (error)
*error = tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE));
return TorrentInfo();
}
QByteArray data; QByteArray data;
try try
@ -161,26 +141,21 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
} }
catch (const std::bad_alloc &e) catch (const std::bad_alloc &e)
{ {
if (error) return nonstd::make_unexpected(tr("Torrent file read error: %1").arg(e.what()));
*error = tr("Torrent file read error: %1").arg(e.what());
return TorrentInfo();
} }
if (data.size() != file.size()) if (data.size() != file.size())
{ return nonstd::make_unexpected(tr("Torrent file read error: size mismatch"));
if (error)
*error = tr("Torrent file read error: size mismatch");
return TorrentInfo();
}
file.close(); file.close();
return load(data, error); return load(data);
} }
void TorrentInfo::saveToFile(const QString &path) const nonstd::expected<void, QString> TorrentInfo::saveToFile(const QString &path) const
{ {
if (!isValid()) if (!isValid())
throw RuntimeError {tr("Invalid metadata")}; return nonstd::make_unexpected(tr("Invalid metadata"));
try try
{ {
@ -188,12 +163,14 @@ void TorrentInfo::saveToFile(const QString &path) const
const lt::entry torrentEntry = torrentCreator.generate(); const lt::entry torrentEntry = torrentCreator.generate();
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry); const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry);
if (!result) if (!result)
throw RuntimeError(result.error()); return result.get_unexpected();
} }
catch (const lt::system_error &err) catch (const lt::system_error &err)
{ {
throw RuntimeError(QString::fromLocal8Bit(err.what())); return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
} }
return {};
} }
bool TorrentInfo::isValid() const bool TorrentInfo::isValid() const

7
src/base/bittorrent/torrentinfo.h

@ -33,6 +33,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QtContainerFwd> #include <QtContainerFwd>
#include "base/3rdparty/expected.hpp"
#include "base/indexrange.h" #include "base/indexrange.h"
#include "abstractfilestorage.h" #include "abstractfilestorage.h"
#include "torrentcontentlayout.h" #include "torrentcontentlayout.h"
@ -55,9 +56,9 @@ namespace BitTorrent
explicit TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo = {}); explicit TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo = {});
TorrentInfo(const TorrentInfo &other); TorrentInfo(const TorrentInfo &other);
static TorrentInfo load(const QByteArray &data, QString *error = nullptr) noexcept; static nonstd::expected<TorrentInfo, QString> load(const QByteArray &data) noexcept;
static TorrentInfo loadFromFile(const QString &path, QString *error = nullptr) noexcept; static nonstd::expected<TorrentInfo, QString> loadFromFile(const QString &path) noexcept;
void saveToFile(const QString &path) const; nonstd::expected<void, QString> saveToFile(const QString &path) const;
TorrentInfo &operator=(const TorrentInfo &other); TorrentInfo &operator=(const TorrentInfo &other);

96
src/base/rss/rss_session.cpp

@ -142,67 +142,59 @@ Session *Session::instance()
return m_instance; return m_instance;
} }
bool Session::addFolder(const QString &path, QString *error) nonstd::expected<void, QString> Session::addFolder(const QString &path)
{ {
Folder *destFolder = prepareItemDest(path, error); const nonstd::expected<Folder *, QString> result = prepareItemDest(path);
if (!destFolder) if (!result)
return false; return result.get_unexpected();
const auto destFolder = result.value();
addItem(new Folder(path), destFolder); addItem(new Folder(path), destFolder);
store(); store();
return true; return {};
} }
bool Session::addFeed(const QString &url, const QString &path, QString *error) nonstd::expected<void, QString> Session::addFeed(const QString &url, const QString &path)
{ {
if (m_feedsByURL.contains(url)) if (m_feedsByURL.contains(url))
{ return nonstd::make_unexpected(tr("RSS feed with given URL already exists: %1.").arg(url));
if (error)
*error = tr("RSS feed with given URL already exists: %1.").arg(url);
return false;
}
Folder *destFolder = prepareItemDest(path, error); const nonstd::expected<Folder *, QString> result = prepareItemDest(path);
if (!destFolder) if (!result)
return false; return result.get_unexpected();
const auto destFolder = result.value();
addItem(new Feed(generateUID(), url, path, this), destFolder); addItem(new Feed(generateUID(), url, path, this), destFolder);
store(); store();
if (m_processingEnabled) if (m_processingEnabled)
feedByURL(url)->refresh(); feedByURL(url)->refresh();
return true;
return {};
} }
bool Session::moveItem(const QString &itemPath, const QString &destPath, QString *error) nonstd::expected<void, QString> Session::moveItem(const QString &itemPath, const QString &destPath)
{ {
if (itemPath.isEmpty()) if (itemPath.isEmpty())
{ return nonstd::make_unexpected(tr("Cannot move root folder."));
if (error)
*error = tr("Cannot move root folder.");
return false;
}
auto item = m_itemsByPath.value(itemPath); auto item = m_itemsByPath.value(itemPath);
if (!item) if (!item)
{ return nonstd::make_unexpected(tr("Item doesn't exist: %1.").arg(itemPath));
if (error)
*error = tr("Item doesn't exist: %1.").arg(itemPath);
return false;
}
return moveItem(item, destPath, error); return moveItem(item, destPath);
} }
bool Session::moveItem(Item *item, const QString &destPath, QString *error) nonstd::expected<void, QString> Session::moveItem(Item *item, const QString &destPath)
{ {
Q_ASSERT(item); Q_ASSERT(item);
Q_ASSERT(item != rootFolder()); Q_ASSERT(item != rootFolder());
Folder *destFolder = prepareItemDest(destPath, error); const nonstd::expected<Folder *, QString> result = prepareItemDest(destPath);
if (!destFolder) if (!result)
return false; return result.get_unexpected();
auto srcFolder = static_cast<Folder *>(m_itemsByPath.value(Item::parentPath(item->path()))); auto srcFolder = static_cast<Folder *>(m_itemsByPath.value(Item::parentPath(item->path())));
const auto destFolder = result.value();
if (srcFolder != destFolder) if (srcFolder != destFolder)
{ {
srcFolder->removeItem(item); srcFolder->removeItem(item);
@ -211,25 +203,17 @@ bool Session::moveItem(Item *item, const QString &destPath, QString *error)
m_itemsByPath.insert(destPath, m_itemsByPath.take(item->path())); m_itemsByPath.insert(destPath, m_itemsByPath.take(item->path()));
item->setPath(destPath); item->setPath(destPath);
store(); store();
return true; return {};
} }
bool Session::removeItem(const QString &itemPath, QString *error) nonstd::expected<void, QString> Session::removeItem(const QString &itemPath)
{ {
if (itemPath.isEmpty()) if (itemPath.isEmpty())
{ return nonstd::make_unexpected(tr("Cannot delete root folder."));
if (error)
*error = tr("Cannot delete root folder.");
return false;
}
auto item = m_itemsByPath.value(itemPath); auto *item = m_itemsByPath.value(itemPath);
if (!item) if (!item)
{ return nonstd::make_unexpected(tr("Item doesn't exist: %1.").arg(itemPath));
if (error)
*error = tr("Item doesn't exist: %1.").arg(itemPath);
return false;
}
emit itemAboutToBeRemoved(item); emit itemAboutToBeRemoved(item);
item->cleanup(); item->cleanup();
@ -238,7 +222,7 @@ bool Session::removeItem(const QString &itemPath, QString *error)
folder->removeItem(item); folder->removeItem(item);
delete item; delete item;
store(); store();
return true; return {};
} }
QList<Item *> Session::items() const QList<Item *> Session::items() const
@ -395,30 +379,18 @@ void Session::store()
m_confFileStorage->store(FeedsFileName, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson()); m_confFileStorage->store(FeedsFileName, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson());
} }
Folder *Session::prepareItemDest(const QString &path, QString *error) nonstd::expected<Folder *, QString> Session::prepareItemDest(const QString &path)
{ {
if (!Item::isValidPath(path)) if (!Item::isValidPath(path))
{ return nonstd::make_unexpected(tr("Incorrect RSS Item path: %1.").arg(path));
if (error)
*error = tr("Incorrect RSS Item path: %1.").arg(path);
return nullptr;
}
if (m_itemsByPath.contains(path)) if (m_itemsByPath.contains(path))
{ return nonstd::make_unexpected(tr("RSS item with given path already exists: %1.").arg(path));
if (error)
*error = tr("RSS item with given path already exists: %1.").arg(path);
return nullptr;
}
const QString destFolderPath = Item::parentPath(path); const QString destFolderPath = Item::parentPath(path);
auto destFolder = qobject_cast<Folder *>(m_itemsByPath.value(destFolderPath)); const auto destFolder = qobject_cast<Folder *>(m_itemsByPath.value(destFolderPath));
if (!destFolder) if (!destFolder)
{ return nonstd::make_unexpected(tr("Parent folder doesn't exist: %1.").arg(destFolderPath));
if (error)
*error = tr("Parent folder doesn't exist: %1.").arg(destFolderPath);
return nullptr;
}
return destFolder; return destFolder;
} }

15
src/base/rss/rss_session.h

@ -73,6 +73,8 @@
#include <QPointer> #include <QPointer>
#include <QTimer> #include <QTimer>
#include "base/3rdparty/expected.hpp"
class QThread; class QThread;
class Application; class Application;
@ -110,12 +112,11 @@ namespace RSS
int refreshInterval() const; int refreshInterval() const;
void setRefreshInterval(int refreshInterval); void setRefreshInterval(int refreshInterval);
bool addFolder(const QString &path, QString *error = nullptr); nonstd::expected<void, QString> addFolder(const QString &path);
bool addFeed(const QString &url, const QString &path, QString *error = nullptr); nonstd::expected<void, QString> addFeed(const QString &url, const QString &path);
bool moveItem(const QString &itemPath, const QString &destPath nonstd::expected<void, QString> moveItem(const QString &itemPath, const QString &destPath);
, QString *error = nullptr); nonstd::expected<void, QString> moveItem(Item *item, const QString &destPath);
bool moveItem(Item *item, const QString &destPath, QString *error = nullptr); nonstd::expected<void, QString> removeItem(const QString &itemPath);
bool removeItem(const QString &itemPath, QString *error = nullptr);
QList<Item *> items() const; QList<Item *> items() const;
Item *itemByPath(const QString &path) const; Item *itemByPath(const QString &path) const;
@ -146,7 +147,7 @@ namespace RSS
void loadFolder(const QJsonObject &jsonObj, Folder *folder); void loadFolder(const QJsonObject &jsonObj, Folder *folder);
void loadLegacy(); void loadLegacy();
void store(); void store();
Folder *prepareItemDest(const QString &path, QString *error); nonstd::expected<Folder *, QString> prepareItemDest(const QString &path);
Folder *addSubfolder(const QString &name, Folder *parentFolder); Folder *addSubfolder(const QString &name, Folder *parentFolder);
Feed *addFeedToFolder(const QUuid &uid, const QString &url, const QString &name, Folder *parentFolder); Feed *addFeedToFolder(const QUuid &uid, const QString &url, const QString &name, Folder *parentFolder);
void addItem(Item *item, Folder *destFolder); void addItem(Item *item, Folder *destFolder);

12
src/base/torrentfileswatcher.cpp

@ -526,10 +526,10 @@ void TorrentFilesWatcher::Worker::processFolder(const QString &path, const QStri
} }
else else
{ {
const auto torrentInfo = BitTorrent::TorrentInfo::loadFromFile(filePath); const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(filePath);
if (torrentInfo.isValid()) if (result)
{ {
emit torrentFound(torrentInfo, addTorrentParams); emit torrentFound(result.value(), addTorrentParams);
Utils::Fs::forceRemove(filePath); Utils::Fs::forceRemove(filePath);
} }
else else
@ -567,8 +567,8 @@ void TorrentFilesWatcher::Worker::processFailedTorrents()
if (!QFile::exists(torrentPath)) if (!QFile::exists(torrentPath))
return true; return true;
const auto torrentInfo = BitTorrent::TorrentInfo::loadFromFile(torrentPath); const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(torrentPath);
if (torrentInfo.isValid()) if (result)
{ {
BitTorrent::AddTorrentParams addTorrentParams = options.addTorrentParams; BitTorrent::AddTorrentParams addTorrentParams = options.addTorrentParams;
const QString exactDirPath = QFileInfo(torrentPath).canonicalPath(); const QString exactDirPath = QFileInfo(torrentPath).canonicalPath();
@ -578,7 +578,7 @@ void TorrentFilesWatcher::Worker::processFailedTorrents()
addTorrentParams.savePath = QDir(addTorrentParams.savePath).filePath(subdirPath); addTorrentParams.savePath = QDir(addTorrentParams.savePath).filePath(subdirPath);
} }
emit torrentFound(torrentInfo, addTorrentParams); emit torrentFound(result.value(), addTorrentParams);
Utils::Fs::forceRemove(torrentPath); Utils::Fs::forceRemove(torrentPath);
return true; return true;

52
src/gui/addnewtorrentdialog.cpp

@ -43,7 +43,6 @@
#include "base/bittorrent/magneturi.h" #include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrent.h" #include "base/bittorrent/torrent.h"
#include "base/exceptions.h"
#include "base/global.h" #include "base/global.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/settingsstorage.h" #include "base/settingsstorage.h"
@ -252,13 +251,13 @@ bool AddNewTorrentDialog::loadTorrentFile(const QString &torrentPath)
? QUrl::fromEncoded(torrentPath.toLocal8Bit()).toLocalFile() ? QUrl::fromEncoded(torrentPath.toLocal8Bit()).toLocalFile()
: torrentPath; : torrentPath;
QString error; const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(decodedPath);
m_torrentInfo = BitTorrent::TorrentInfo::loadFromFile(decodedPath, &error); m_torrentInfo = result.value_or(BitTorrent::TorrentInfo());
if (!m_torrentInfo.isValid()) if (!result)
{ {
RaisedMessageBox::critical(this, tr("Invalid torrent") RaisedMessageBox::critical(this, tr("Invalid torrent")
, tr("Failed to load the torrent: %1.\nError: %2", "Don't remove the '\n' characters. They insert a newline.") , tr("Failed to load the torrent: %1.\nError: %2", "Don't remove the '\n' characters. They insert a newline.")
.arg(Utils::Fs::toNativePath(decodedPath), error)); .arg(Utils::Fs::toNativePath(decodedPath), result.error()));
return false; return false;
} }
@ -473,14 +472,11 @@ void AddNewTorrentDialog::saveTorrentFile()
if (!path.endsWith(torrentFileExtension, Qt::CaseInsensitive)) if (!path.endsWith(torrentFileExtension, Qt::CaseInsensitive))
path += torrentFileExtension; path += torrentFileExtension;
try const nonstd::expected<void, QString> result = m_torrentInfo.saveToFile(path);
{ if (!result)
m_torrentInfo.saveToFile(path);
}
catch (const RuntimeError &err)
{ {
QMessageBox::critical(this, tr("I/O Error") QMessageBox::critical(this, tr("I/O Error")
, tr("Couldn't export torrent metadata file '%1'. Reason: %2.").arg(path, err.message())); , tr("Couldn't export torrent metadata file '%1'. Reason: %2.").arg(path, result.error()));
} }
} }
@ -746,36 +742,38 @@ void AddNewTorrentDialog::setupTreeview()
updateDiskSpaceLabel(); updateDiskSpaceLabel();
} }
void AddNewTorrentDialog::handleDownloadFinished(const Net::DownloadResult &result) void AddNewTorrentDialog::handleDownloadFinished(const Net::DownloadResult &downloadResult)
{ {
QString error; switch (downloadResult.status)
switch (result.status)
{ {
case Net::DownloadStatus::Success: case Net::DownloadStatus::Success:
m_torrentInfo = BitTorrent::TorrentInfo::load(result.data, &error);
if (!m_torrentInfo.isValid())
{ {
RaisedMessageBox::critical(this, tr("Invalid torrent"), tr("Failed to load from URL: %1.\nError: %2") const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::load(downloadResult.data);
.arg(result.url, error)); m_torrentInfo = result.value_or(BitTorrent::TorrentInfo());
return; if (!result)
} {
RaisedMessageBox::critical(this, tr("Invalid torrent"), tr("Failed to load from URL: %1.\nError: %2")
.arg(downloadResult.url, result.error()));
return;
}
m_torrentGuard = std::make_unique<TorrentFileGuard>(); m_torrentGuard = std::make_unique<TorrentFileGuard>();
if (loadTorrentImpl()) if (loadTorrentImpl())
open(); open();
else else
deleteLater(); deleteLater();
}
break; break;
case Net::DownloadStatus::RedirectedToMagnet: case Net::DownloadStatus::RedirectedToMagnet:
if (loadMagnet(BitTorrent::MagnetUri(result.magnet))) if (loadMagnet(BitTorrent::MagnetUri(downloadResult.magnet)))
open(); open();
else else
deleteLater(); deleteLater();
break; break;
default: default:
RaisedMessageBox::critical(this, tr("Download Error"), RaisedMessageBox::critical(this, tr("Download Error"),
tr("Cannot download '%1': %2").arg(result.url, result.errorString)); tr("Cannot download '%1': %2").arg(downloadResult.url, downloadResult.errorString));
deleteLater(); deleteLater();
} }
} }

2
src/gui/addnewtorrentdialog.h

@ -82,7 +82,7 @@ private slots:
void updateDiskSpaceLabel(); void updateDiskSpaceLabel();
void onSavePathChanged(const QString &newPath); void onSavePathChanged(const QString &newPath);
void updateMetadata(const BitTorrent::TorrentInfo &metadata); void updateMetadata(const BitTorrent::TorrentInfo &metadata);
void handleDownloadFinished(const Net::DownloadResult &result); void handleDownloadFinished(const Net::DownloadResult &downloadResult);
void TMMChanged(int index); void TMMChanged(int index);
void categoryChanged(int index); void categoryChanged(int index);
void doNotDeleteTorrentClicked(bool checked); void doNotDeleteTorrentClicked(bool checked);

18
src/gui/rss/rsswidget.cpp

@ -246,10 +246,10 @@ void RSSWidget::askNewFolder()
? RSS::Session::instance()->rootFolder() ? RSS::Session::instance()->rootFolder()
: qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem))); : qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem)));
QString error;
const QString newFolderPath = RSS::Item::joinPath(rssDestFolder->path(), newName); const QString newFolderPath = RSS::Item::joinPath(rssDestFolder->path(), newName);
if (!RSS::Session::instance()->addFolder(newFolderPath, &error)) const nonstd::expected<void, QString> result = RSS::Session::instance()->addFolder(newFolderPath);
QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); if (!result)
QMessageBox::warning(this, "qBittorrent", result.error(), QMessageBox::Ok);
// Expand destination folder to display new feed // Expand destination folder to display new feed
if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) if (destItem && (destItem != m_feedListWidget->stickyUnreadItem()))
@ -287,11 +287,11 @@ void RSSWidget::on_newFeedButton_clicked()
? RSS::Session::instance()->rootFolder() ? RSS::Session::instance()->rootFolder()
: qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem))); : qobject_cast<RSS::Folder *>(m_feedListWidget->getRSSItem(destItem)));
QString error;
// NOTE: We still add feed using legacy way (with URL as feed name) // NOTE: We still add feed using legacy way (with URL as feed name)
const QString newFeedPath = RSS::Item::joinPath(rssDestFolder->path(), newURL); const QString newFeedPath = RSS::Item::joinPath(rssDestFolder->path(), newURL);
if (!RSS::Session::instance()->addFeed(newURL, newFeedPath, &error)) const nonstd::expected<void, QString> result = RSS::Session::instance()->addFeed(newURL, newFeedPath);
QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); if (!result)
QMessageBox::warning(this, "qBittorrent", result.error(), QMessageBox::Ok);
// Expand destination folder to display new feed // Expand destination folder to display new feed
if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) if (destItem && (destItem != m_feedListWidget->stickyUnreadItem()))
@ -411,10 +411,10 @@ void RSSWidget::renameSelectedRSSItem()
// Check if name is already taken // Check if name is already taken
if (!ok) return; if (!ok) return;
QString error; const nonstd::expected<void, QString> result = RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(parentPath, newName));
if (!RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(parentPath, newName), &error)) if (!result)
{ {
QMessageBox::warning(nullptr, tr("Rename failed"), error); QMessageBox::warning(nullptr, tr("Rename failed"), result.error());
ok = false; ok = false;
} }
} while (!ok); } while (!ok);

6
src/gui/torrentcreatordialog.cpp

@ -234,8 +234,8 @@ void TorrentCreatorDialog::handleCreationSuccess(const QString &path, const QStr
if (m_ui->checkStartSeeding->isChecked()) if (m_ui->checkStartSeeding->isChecked())
{ {
// Create save path temp data // Create save path temp data
const BitTorrent::TorrentInfo info = BitTorrent::TorrentInfo::loadFromFile(Utils::Fs::toNativePath(path)); const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(Utils::Fs::toNativePath(path));
if (!info.isValid()) if (!result)
{ {
QMessageBox::critical(this, tr("Torrent creation failed"), tr("Reason: Created torrent is invalid. It won't be added to download list.")); QMessageBox::critical(this, tr("Torrent creation failed"), tr("Reason: Created torrent is invalid. It won't be added to download list."));
return; return;
@ -251,7 +251,7 @@ void TorrentCreatorDialog::handleCreationSuccess(const QString &path, const QStr
} }
params.useAutoTMM = false; // otherwise if it is on by default, it will overwrite `savePath` to the default save path params.useAutoTMM = false; // otherwise if it is on by default, it will overwrite `savePath` to the default save path
BitTorrent::Session::instance()->addTorrent(info, params); BitTorrent::Session::instance()->addTorrent(result.value(), params);
} }
QMessageBox::information(this, tr("Torrent creator") QMessageBox::information(this, tr("Torrent creator")
, QString::fromLatin1("%1\n%2").arg(tr("Torrent created:"), Utils::Fs::toNativePath(path))); , QString::fromLatin1("%1\n%2").arg(tr("Torrent created:"), Utils::Fs::toNativePath(path)));

24
src/webui/api/rsscontroller.cpp

@ -50,9 +50,9 @@ void RSSController::addFolderAction()
requireParams({"path"}); requireParams({"path"});
const QString path = params()["path"].trimmed(); const QString path = params()["path"].trimmed();
QString error; const nonstd::expected<void, QString> result = RSS::Session::instance()->addFolder(path);
if (!RSS::Session::instance()->addFolder(path, &error)) if (!result)
throw APIError(APIErrorType::Conflict, error); throw APIError(APIErrorType::Conflict, result.error());
} }
void RSSController::addFeedAction() void RSSController::addFeedAction()
@ -61,9 +61,9 @@ void RSSController::addFeedAction()
const QString url = params()["url"].trimmed(); const QString url = params()["url"].trimmed();
const QString path = params()["path"].trimmed(); const QString path = params()["path"].trimmed();
QString error; const nonstd::expected<void, QString> result = RSS::Session::instance()->addFeed(url, (path.isEmpty() ? url : path));
if (!RSS::Session::instance()->addFeed(url, (path.isEmpty() ? url : path), &error)) if (!result)
throw APIError(APIErrorType::Conflict, error); throw APIError(APIErrorType::Conflict, result.error());
} }
void RSSController::removeItemAction() void RSSController::removeItemAction()
@ -71,9 +71,9 @@ void RSSController::removeItemAction()
requireParams({"path"}); requireParams({"path"});
const QString path = params()["path"].trimmed(); const QString path = params()["path"].trimmed();
QString error; const nonstd::expected<void, QString> result = RSS::Session::instance()->removeItem(path);
if (!RSS::Session::instance()->removeItem(path, &error)) if (!result)
throw APIError(APIErrorType::Conflict, error); throw APIError(APIErrorType::Conflict, result.error());
} }
void RSSController::moveItemAction() void RSSController::moveItemAction()
@ -82,9 +82,9 @@ void RSSController::moveItemAction()
const QString itemPath = params()["itemPath"].trimmed(); const QString itemPath = params()["itemPath"].trimmed();
const QString destPath = params()["destPath"].trimmed(); const QString destPath = params()["destPath"].trimmed();
QString error; const nonstd::expected<void, QString> result = RSS::Session::instance()->moveItem(itemPath, destPath);
if (!RSS::Session::instance()->moveItem(itemPath, destPath, &error)) if (!result)
throw APIError(APIErrorType::Conflict, error); throw APIError(APIErrorType::Conflict, result.error());
} }
void RSSController::itemsAction() void RSSController::itemsAction()

6
src/webui/api/torrentscontroller.cpp

@ -701,14 +701,14 @@ void TorrentsController::addAction()
for (auto it = data().constBegin(); it != data().constEnd(); ++it) for (auto it = data().constBegin(); it != data().constEnd(); ++it)
{ {
const BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::load(it.value()); const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::load(it.value());
if (!torrentInfo.isValid()) if (!result)
{ {
throw APIError(APIErrorType::BadData throw APIError(APIErrorType::BadData
, tr("Error: '%1' is not a valid torrent file.").arg(it.key())); , tr("Error: '%1' is not a valid torrent file.").arg(it.key()));
} }
partialSuccess |= BitTorrent::Session::instance()->addTorrent(torrentInfo, addTorrentParams); partialSuccess |= BitTorrent::Session::instance()->addTorrent(result.value(), addTorrentParams);
} }
if (partialSuccess) if (partialSuccess)

Loading…
Cancel
Save