diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp
index 40a2c8f5a..79f699ff4 100644
--- a/src/gui/transferlistwidget.cpp
+++ b/src/gui/transferlistwidget.cpp
@@ -527,6 +527,15 @@ void TransferListWidget::copySelectedNames() const
qApp->clipboard()->setText(torrent_names.join("\n"));
}
+void TransferListWidget::copySelectedHashes() const
+{
+ QStringList torrentHashes;
+ foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
+ torrentHashes << torrent->hash();
+
+ qApp->clipboard()->setText(torrentHashes.join('\n'));
+}
+
void TransferListWidget::hidePriorityColumn(bool hide)
{
qDebug("hidePriorityColumn(%d)", hide);
@@ -870,6 +879,8 @@ void TransferListWidget::displayListMenu(const QPoint&)
connect(&actionCopy_magnet_link, SIGNAL(triggered()), this, SLOT(copySelectedMagnetURIs()));
QAction actionCopy_name(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), 0);
connect(&actionCopy_name, SIGNAL(triggered()), this, SLOT(copySelectedNames()));
+ QAction actionCopyHash(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), 0);
+ connect(&actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes);
QAction actionSuper_seeding_mode(tr("Super seeding mode"), 0);
actionSuper_seeding_mode.setCheckable(true);
connect(&actionSuper_seeding_mode, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSuperSeeding()));
@@ -1081,6 +1092,7 @@ void TransferListWidget::displayListMenu(const QPoint&)
listMenu.addSeparator();
listMenu.addAction(&actionCopy_name);
listMenu.addAction(&actionCopy_magnet_link);
+ listMenu.addAction(&actionCopyHash);
// Call menu
QAction *act = 0;
act = listMenu.exec(QCursor::pos());
diff --git a/src/gui/transferlistwidget.h b/src/gui/transferlistwidget.h
index c0265c1b7..0686f4466 100644
--- a/src/gui/transferlistwidget.h
+++ b/src/gui/transferlistwidget.h
@@ -82,6 +82,7 @@ public slots:
void bottomPrioSelectedTorrents();
void copySelectedMagnetURIs() const;
void copySelectedNames() const;
+ void copySelectedHashes() const;
void openSelectedTorrentsFolder() const;
void recheckSelectedTorrents();
void setDlLimitSelectedTorrents();
diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp
index 4eef96403..827505fed 100644
--- a/src/webui/btjson.cpp
+++ b/src/webui/btjson.cpp
@@ -76,6 +76,7 @@ static const int CACHE_DURATION_MS = 1500; // 1500ms
// Torrent keys
static const char KEY_TORRENT_HASH[] = "hash";
static const char KEY_TORRENT_NAME[] = "name";
+static const char KEY_TORRENT_MAGNET_URI[] = "magnet_uri";
static const char KEY_TORRENT_SIZE[] = "size";
static const char KEY_TORRENT_PROGRESS[] = "progress";
static const char KEY_TORRENT_DLSPEED[] = "dlspeed";
@@ -789,6 +790,7 @@ QVariantMap toMap(BitTorrent::TorrentHandle *const torrent)
QVariantMap ret;
ret[KEY_TORRENT_HASH] = QString(torrent->hash());
ret[KEY_TORRENT_NAME] = torrent->name();
+ ret[KEY_TORRENT_MAGNET_URI] = torrent->toMagnetUri();
ret[KEY_TORRENT_SIZE] = torrent->wantedSize();
ret[KEY_TORRENT_PROGRESS] = torrent->progress();
ret[KEY_TORRENT_DLSPEED] = torrent->downloadPayloadRate();
diff --git a/src/webui/webui.qrc b/src/webui/webui.qrc
index e7395c4cd..833ea74ed 100644
--- a/src/webui/webui.qrc
+++ b/src/webui/webui.qrc
@@ -9,6 +9,7 @@