Allow to copy content paths of selected torrents

Closes #23227.
PR #23239.

---------

Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
This commit is contained in:
Mark Yu 2025-09-14 04:42:59 -04:00 committed by GitHub
parent 919520b4c3
commit 8e14541236
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 36 additions and 0 deletions

View File

@ -525,6 +525,19 @@ void TransferListWidget::copySelectedNames() const
qApp->clipboard()->setText(torrentNames.join(u'\n'));
}
void TransferListWidget::copyContentPaths() const
{
QStringList contentPaths;
for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents()))
{
const Path contentPath = torrent->contentPath();
if (!contentPath.isEmpty())
contentPaths << contentPath.toString();
}
qApp->clipboard()->setText(contentPaths.join(u'\n'));
}
void TransferListWidget::copySelectedInfohashes(const CopyInfohashPolicy policy) const
{
const auto selectedTorrents = getSelectedTorrents();
@ -1000,6 +1013,8 @@ void TransferListWidget::displayListMenu()
connect(actionCopyHash1, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version1); });
auto *actionCopyHash2 = new QAction(UIThemeManager::instance()->getIcon(u"hash"_s, u"edit-copy"_s), tr("Info h&ash v2"), listMenu);
connect(actionCopyHash2, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version2); });
auto *actionCopyContentPath = new QAction(UIThemeManager::instance()->getIcon(u"directory"_s, u"edit-copy"_s), tr("Content &Path"), listMenu);
connect(actionCopyContentPath, &QAction::triggered, this, &TransferListWidget::copyContentPaths);
auto *actionSuperSeedingMode = new TriStateAction(tr("Super seeding mode"), listMenu);
connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSuperSeeding);
auto *actionRename = new QAction(UIThemeManager::instance()->getIcon(u"edit-rename"_s), tr("Re&name..."), listMenu);
@ -1282,6 +1297,7 @@ void TransferListWidget::displayListMenu()
copySubMenu->addAction(actionCopyMagnetLink);
copySubMenu->addAction(actionCopyID);
copySubMenu->addAction(actionCopyComment);
copySubMenu->addAction(actionCopyContentPath);
actionExportTorrent->setToolTip(tr("Exported torrent is not necessarily the same as the imported"));
listMenu->addAction(actionExportTorrent);

View File

@ -85,6 +85,7 @@ public slots:
void bottomQueuePosSelectedTorrents();
void copySelectedMagnetURIs() const;
void copySelectedNames() const;
void copyContentPaths() const;
void copySelectedInfohashes(CopyInfohashPolicy policy) const;
void copySelectedIDs() const;
void copySelectedComments() const;

View File

@ -219,6 +219,7 @@
<li><a href="#" id="copyMagnetLink" class="copyToClipboard"><img src="images/torrent-magnet.svg" alt="QBT_TR(Magnet link)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Magnet link)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#" id="copyID" class="copyToClipboard"><img src="images/help-about.svg" alt="QBT_TR(Torrent ID)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Torrent ID)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#" id="copyComment" class="copyToClipboard"><img src="images/edit-copy.svg" alt="QBT_TR(Comment)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Comment)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#" id="copyContentPath" class="copyToClipboard"><img src="images/directory.svg" alt="QBT_TR(Content Path)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Content Path)QBT_TR[CONTEXT=TransferListWidget]</a></li>
</ul>
</li>
<li>

View File

@ -1886,6 +1886,9 @@ window.addEventListener("DOMContentLoaded", (event) => {
case "copyComment":
setupClickEvent(copyCommentFN);
break;
case "copyContentPath":
setupClickEvent(copyContentPathFN);
break;
}
}

View File

@ -153,6 +153,7 @@ let copyInfohashFN = (policy) => {};
let copyMagnetLinkFN = () => {};
let copyIdFN = () => {};
let copyCommentFN = () => {};
let copyContentPathFN = () => {};
let setQueuePositionFN = () => {};
let exportTorrentFN = () => {};
@ -1219,6 +1220,20 @@ const initializeWindows = () => {
return comments.join("\n---------\n");
};
copyContentPathFN = () => {
const selectedRows = torrentsTable.selectedRowsIds();
const contentPaths = [];
if (selectedRows.length > 0) {
const rows = torrentsTable.getFilteredAndSortedRows();
for (const hash of selectedRows) {
const contentPath = rows[hash].full_data.content_path;
if ((contentPath !== null) && (contentPath.length > 0))
contentPaths.push(contentPath);
}
}
return contentPaths.join("\n");
};
exportTorrentFN = async () => {
const hashes = torrentsTable.selectedRowsIds();
for (const hash of hashes) {