Browse Source

Add "Export .torrent" action

adaptive-webui-19844
Chocobo1 3 years ago
parent
commit
a90ade0446
No known key found for this signature in database
GPG Key ID: 210D9C873253A68C
  1. 2
      src/base/bittorrent/torrent.h
  2. 33
      src/base/bittorrent/torrentimpl.cpp
  3. 1
      src/base/bittorrent/torrentimpl.h
  4. 1
      src/base/bittorrent/torrentinfo.cpp
  5. 1
      src/base/bittorrent/torrentinfo.h
  6. 60
      src/gui/transferlistwidget.cpp
  7. 3
      src/gui/transferlistwidget.h

2
src/base/bittorrent/torrent.h

@ -34,6 +34,7 @@
#include <QMetaType> #include <QMetaType>
#include <QString> #include <QString>
#include "base/3rdparty/expected.hpp"
#include "base/pathfwd.h" #include "base/pathfwd.h"
#include "base/tagset.h" #include "base/tagset.h"
#include "abstractfilestorage.h" #include "abstractfilestorage.h"
@ -300,6 +301,7 @@ namespace BitTorrent
virtual void clearPeers() = 0; virtual void clearPeers() = 0;
virtual QString createMagnetURI() const = 0; virtual QString createMagnetURI() const = 0;
virtual nonstd::expected<void, QString> exportToFile(const Path &path) const = 0;
TorrentID id() const; TorrentID id() const;
bool isResumed() const; bool isResumed() const;

33
src/base/bittorrent/torrentimpl.cpp

@ -35,6 +35,7 @@
#include <libtorrent/address.hpp> #include <libtorrent/address.hpp>
#include <libtorrent/alert_types.hpp> #include <libtorrent/alert_types.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/magnet_uri.hpp> #include <libtorrent/magnet_uri.hpp>
#include <libtorrent/session.hpp> #include <libtorrent/session.hpp>
#include <libtorrent/storage_defs.hpp> #include <libtorrent/storage_defs.hpp>
@ -53,6 +54,7 @@
#include "base/logger.h" #include "base/logger.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
#include "base/utils/io.h"
#include "base/utils/string.h" #include "base/utils/string.h"
#include "common.h" #include "common.h"
#include "downloadpriority.h" #include "downloadpriority.h"
@ -2232,6 +2234,37 @@ QString TorrentImpl::createMagnetURI() const
return QString::fromStdString(lt::make_magnet_uri(m_nativeHandle)); return QString::fromStdString(lt::make_magnet_uri(m_nativeHandle));
} }
nonstd::expected<void, QString> TorrentImpl::exportToFile(const Path &path) const
{
if (!hasMetadata())
return nonstd::make_unexpected(tr("Missing metadata"));
try
{
#ifdef QBT_USES_LIBTORRENT2
const std::shared_ptr<lt::torrent_info> completeTorrentInfo = m_nativeHandle.torrent_file_with_hashes();
const std::shared_ptr<lt::torrent_info> torrentInfo = {completeTorrentInfo ? completeTorrentInfo : info().nativeInfo()};
#else
const std::shared_ptr<lt::torrent_info> torrentInfo = info().nativeInfo();
#endif
auto creator = lt::create_torrent(*torrentInfo);
for (const TrackerEntry &entry : asConst(trackers()))
creator.add_tracker(entry.url.toStdString(), entry.tier);
const lt::entry torrentEntry = creator.generate();
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry);
if (!result)
return result.get_unexpected();
}
catch (const lt::system_error &err)
{
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
}
return {};
}
void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities) void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
{ {
if (!hasMetadata()) return; if (!hasMetadata()) return;

1
src/base/bittorrent/torrentimpl.h

@ -227,6 +227,7 @@ namespace BitTorrent
void clearPeers() override; void clearPeers() override;
QString createMagnetURI() const override; QString createMagnetURI() const override;
nonstd::expected<void, QString> exportToFile(const Path &path) const;
bool needSaveResumeData() const; bool needSaveResumeData() const;

1
src/base/bittorrent/torrentinfo.cpp

@ -38,7 +38,6 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QUrl> #include <QUrl>
#include <QVector>
#include "base/global.h" #include "base/global.h"
#include "base/path.h" #include "base/path.h"

1
src/base/bittorrent/torrentinfo.h

@ -32,6 +32,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QtContainerFwd> #include <QtContainerFwd>
#include <QVector>
#include "base/3rdparty/expected.hpp" #include "base/3rdparty/expected.hpp"
#include "base/indexrange.h" #include "base/indexrange.h"

60
src/gui/transferlistwidget.cpp

@ -47,6 +47,7 @@
#include "base/bittorrent/trackerentry.h" #include "base/bittorrent/trackerentry.h"
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/path.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/torrentfilter.h" #include "base/torrentfilter.h"
#include "base/utils/compare.h" #include "base/utils/compare.h"
@ -757,6 +758,57 @@ void TransferListWidget::editTorrentTrackers()
trackerDialog->open(); trackerDialog->open();
} }
void TransferListWidget::exportTorrent()
{
if (getSelectedTorrents().isEmpty())
return;
auto fileDialog = new QFileDialog(this, tr("Choose folder to save exported .torrent files"));
fileDialog->setAttribute(Qt::WA_DeleteOnClose);
fileDialog->setFileMode(QFileDialog::Directory);
fileDialog->setOptions(QFileDialog::ShowDirsOnly);
connect(fileDialog, &QFileDialog::fileSelected, this, [this](const QString &dir)
{
const QVector<BitTorrent::Torrent *> torrents = getSelectedTorrents();
if (torrents.isEmpty())
return;
const Path savePath {dir};
if (!savePath.exists())
return;
const QString errorMsg = tr("Export .torrent file failed. Torrent: \"%1\". Save path: \"%2\". Reason: \"%3\"");
bool hasError = false;
for (const BitTorrent::Torrent *torrent : torrents)
{
const Path filePath = savePath / Path(torrent->name() + u".torrent");
if (filePath.exists())
{
LogMsg(errorMsg.arg(torrent->name(), filePath.toString(), tr("A file with the same name already exists")) , Log::WARNING);
hasError = true;
continue;
}
const nonstd::expected<void, QString> result = torrent->exportToFile(filePath);
if (!result)
{
LogMsg(errorMsg.arg(torrent->name(), filePath.toString(), result.error()) , Log::WARNING);
hasError = true;
continue;
}
}
if (hasError)
{
QMessageBox::warning(this, tr("Export .torrent file error")
, tr("Errors occured when exporting .torrent files. Check execution log for details."));
}
});
fileDialog->open();
}
void TransferListWidget::confirmRemoveAllTagsForSelection() void TransferListWidget::confirmRemoveAllTagsForSelection()
{ {
QMessageBox::StandardButton response = QMessageBox::question( QMessageBox::StandardButton response = QMessageBox::question(
@ -906,6 +958,8 @@ void TransferListWidget::displayListMenu()
connect(actionAutoTMM, &QAction::triggered, this, &TransferListWidget::setSelectedAutoTMMEnabled); connect(actionAutoTMM, &QAction::triggered, this, &TransferListWidget::setSelectedAutoTMMEnabled);
auto *actionEditTracker = new QAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs), tr("Edit trackers..."), listMenu); auto *actionEditTracker = new QAction(UIThemeManager::instance()->getIcon(u"edit-rename"_qs), tr("Edit trackers..."), listMenu);
connect(actionEditTracker, &QAction::triggered, this, &TransferListWidget::editTorrentTrackers); connect(actionEditTracker, &QAction::triggered, this, &TransferListWidget::editTorrentTrackers);
auto *actionExportTorrent = new QAction(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Export .torrent..."), listMenu);
connect(actionExportTorrent, &QAction::triggered, this, &TransferListWidget::exportTorrent);
// End of actions // End of actions
// Enable/disable pause/start action given the DL state // Enable/disable pause/start action given the DL state
@ -1161,8 +1215,7 @@ void TransferListWidget::displayListMenu()
queueMenu->addAction(actionBottomQueuePos); queueMenu->addAction(actionBottomQueuePos);
} }
QMenu *copySubMenu = listMenu->addMenu( QMenu *copySubMenu = listMenu->addMenu(UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy"));
UIThemeManager::instance()->getIcon(u"edit-copy"_qs), tr("Copy"));
copySubMenu->addAction(actionCopyName); copySubMenu->addAction(actionCopyName);
copySubMenu->addAction(actionCopyHash1); copySubMenu->addAction(actionCopyHash1);
actionCopyHash1->setEnabled(hasInfohashV1); actionCopyHash1->setEnabled(hasInfohashV1);
@ -1171,6 +1224,9 @@ void TransferListWidget::displayListMenu()
copySubMenu->addAction(actionCopyMagnetLink); copySubMenu->addAction(actionCopyMagnetLink);
copySubMenu->addAction(actionCopyID); copySubMenu->addAction(actionCopyID);
actionExportTorrent->setToolTip(u"Exported torrent is not necessarily the same as the imported"_qs);
listMenu->addAction(actionExportTorrent);
listMenu->popup(QCursor::pos()); listMenu->popup(QCursor::pos());
} }

3
src/gui/transferlistwidget.h

@ -34,9 +34,9 @@
#include <QTreeView> #include <QTreeView>
#include "base/bittorrent/infohash.h" #include "base/bittorrent/infohash.h"
#include "base/path.h"
class MainWindow; class MainWindow;
class Path;
class TransferListModel; class TransferListModel;
class TransferListSortModel; class TransferListSortModel;
@ -124,6 +124,7 @@ private:
QVector<BitTorrent::Torrent *> getSelectedTorrents() const; QVector<BitTorrent::Torrent *> getSelectedTorrents() const;
void askAddTagsForSelection(); void askAddTagsForSelection();
void editTorrentTrackers(); void editTorrentTrackers();
void exportTorrent();
void confirmRemoveAllTagsForSelection(); void confirmRemoveAllTagsForSelection();
QStringList askTagsForSelection(const QString &dialogTitle); QStringList askTagsForSelection(const QString &dialogTitle);
void applyToSelectedTorrents(const std::function<void (BitTorrent::Torrent *const)> &fn); void applyToSelectedTorrents(const std::function<void (BitTorrent::Torrent *const)> &fn);

Loading…
Cancel
Save