mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-26 19:26:59 +03:00
Provide v1 and v2 infohashes in UI (#15097)
This commit is contained in:
parent
f6eb29d800
commit
37f227ae74
24 changed files with 285 additions and 106 deletions
|
@ -353,6 +353,12 @@ void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
|
|||
program.replace(i, 2, torrent->tags().join(QLatin1String(",")));
|
||||
break;
|
||||
case u'I':
|
||||
program.replace(i, 2, (torrent->infoHash().v1().isValid() ? torrent->infoHash().v1().toString() : QLatin1String("-")));
|
||||
break;
|
||||
case u'J':
|
||||
program.replace(i, 2, (torrent->infoHash().v2().isValid() ? torrent->infoHash().v2().toString() : QLatin1String("-")));
|
||||
break;
|
||||
case u'K':
|
||||
program.replace(i, 2, torrent->id().toString());
|
||||
break;
|
||||
case u'L':
|
||||
|
|
|
@ -41,6 +41,24 @@ bool BitTorrent::InfoHash::isValid() const
|
|||
return m_valid;
|
||||
}
|
||||
|
||||
SHA1Hash BitTorrent::InfoHash::v1() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
return (m_nativeHash.has_v1() ? SHA1Hash(m_nativeHash.v1) : SHA1Hash());
|
||||
#else
|
||||
return {m_nativeHash};
|
||||
#endif
|
||||
}
|
||||
|
||||
SHA256Hash BitTorrent::InfoHash::v2() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
return (m_nativeHash.has_v2() ? SHA256Hash(m_nativeHash.v2) : SHA256Hash());
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
BitTorrent::TorrentID BitTorrent::InfoHash::toTorrentID() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
|
|
|
@ -69,6 +69,8 @@ namespace BitTorrent
|
|||
InfoHash(const WrappedType &nativeHash);
|
||||
|
||||
bool isValid() const;
|
||||
SHA1Hash v1() const;
|
||||
SHA256Hash v2() const;
|
||||
TorrentID toTorrentID() const;
|
||||
|
||||
operator WrappedType() const;
|
||||
|
|
|
@ -296,7 +296,8 @@ bool AddNewTorrentDialog::loadTorrentImpl()
|
|||
return false;
|
||||
}
|
||||
|
||||
m_ui->labelHashData->setText(torrentID.toString());
|
||||
m_ui->labelInfohash1Data->setText(m_torrentInfo.infoHash().v1().isValid() ? m_torrentInfo.infoHash().v1().toString() : tr("N/A"));
|
||||
m_ui->labelInfohash2Data->setText(m_torrentInfo.infoHash().v2().isValid() ? m_torrentInfo.infoHash().v2().toString() : tr("N/A"));
|
||||
setupTreeview();
|
||||
TMMChanged(m_ui->comboTTM->currentIndex());
|
||||
return true;
|
||||
|
@ -348,7 +349,8 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
|
|||
|
||||
BitTorrent::Session::instance()->downloadMetadata(magnetUri);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
m_ui->labelHashData->setText(torrentID.toString());
|
||||
m_ui->labelInfohash1Data->setText(magnetUri.infoHash().v1().isValid() ? magnetUri.infoHash().v1().toString() : tr("N/A"));
|
||||
m_ui->labelInfohash2Data->setText(magnetUri.infoHash().v2().isValid() ? magnetUri.infoHash().v2().toString() : tr("N/A"));
|
||||
|
||||
m_magnetURI = magnetUri;
|
||||
return true;
|
||||
|
|
|
@ -249,10 +249,10 @@
|
|||
<string>Torrent information</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDate">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelInfohash1">
|
||||
<property name="text">
|
||||
<string>Date:</string>
|
||||
<string>Info hash v1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -262,24 +262,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelDateData"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSize">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelHashData">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgba(0, 0, 0, 0);</string>
|
||||
|
@ -295,7 +278,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>333</width>
|
||||
<width>317</width>
|
||||
<height>69</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -335,14 +318,7 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelHash">
|
||||
<property name="text">
|
||||
<string>Hash:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelComment">
|
||||
<property name="text">
|
||||
<string>Comment:</string>
|
||||
|
@ -352,6 +328,44 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSize">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelInfohash1Data">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDate">
|
||||
<property name="text">
|
||||
<string>Date:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelInfohash2">
|
||||
<property name="text">
|
||||
<string>Info hash v2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="labelInfohash2Data">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -388,7 +388,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||
connect(m_ui->lineEditAutoRun, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->autoRunConsole, &QCheckBox::toggled, this, &ThisType::enableApplyButton);
|
||||
|
||||
const QString autoRunStr = QString("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n %11\n%12")
|
||||
const QString autoRunStr = QString("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n %11\n %12\n %13\n%14")
|
||||
.arg(tr("Supported parameters (case sensitive):")
|
||||
, tr("%N: Torrent name")
|
||||
, tr("%L: Category")
|
||||
|
@ -399,7 +399,9 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
|||
, tr("%C: Number of files")
|
||||
, tr("%Z: Torrent size (bytes)"))
|
||||
.arg(tr("%T: Current tracker")
|
||||
, tr("%I: Info hash")
|
||||
, tr("%I: Info hash v1 (or '-' if unavailable)")
|
||||
, tr("%J: Info hash v2 (or '-' if unavailable)")
|
||||
, tr("%K: Torrent ID (either sha-1 info hash for v1 torrent or truncated sha-256 info hash for v2/hybrid torrent)")
|
||||
, tr("Tip: Encapsulate parameter with quotation marks to avoid text being cut off at whitespace (e.g., \"%N\")"));
|
||||
m_ui->labelAutoRunParam->setText(autoRunStr);
|
||||
|
||||
|
|
|
@ -232,7 +232,8 @@ void PropertiesWidget::clear()
|
|||
m_ui->labelSavePathVal->clear();
|
||||
m_ui->labelCreatedOnVal->clear();
|
||||
m_ui->labelTotalPiecesVal->clear();
|
||||
m_ui->labelHashVal->clear();
|
||||
m_ui->labelInfohash1Val->clear();
|
||||
m_ui->labelInfohash2Val->clear();
|
||||
m_ui->labelCommentVal->clear();
|
||||
m_ui->labelProgressVal->clear();
|
||||
m_ui->labelAverageAvailabilityVal->clear();
|
||||
|
@ -312,9 +313,9 @@ void PropertiesWidget::loadTorrentInfos(BitTorrent::Torrent *const torrent)
|
|||
|
||||
// Save path
|
||||
updateSavePath(m_torrent);
|
||||
// Info hash (Truncated info hash (torrent ID) with libtorrent2)
|
||||
// TODO: Update label for this property to express its meaning more clearly (or change it to display real info hash(es))
|
||||
m_ui->labelHashVal->setText(m_torrent->id().toString());
|
||||
// Info hashes
|
||||
m_ui->labelInfohash1Val->setText(m_torrent->infoHash().v1().isValid() ? m_torrent->infoHash().v1().toString() : tr("N/A"));
|
||||
m_ui->labelInfohash2Val->setText(m_torrent->infoHash().v2().isValid() ? m_torrent->infoHash().v2().toString() : tr("N/A"));
|
||||
m_propListModel->model()->clear();
|
||||
if (m_torrent->hasMetadata())
|
||||
{
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
@ -23,9 +26,6 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedProperties">
|
||||
<property name="currentIndex">
|
||||
|
@ -788,7 +788,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelHash">
|
||||
<widget class="QLabel" name="labelInfohash1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -796,15 +796,31 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Torrent Hash:</string>
|
||||
<string>Info Hash v1:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="5">
|
||||
<widget class="QLabel" name="labelHashVal">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelInfohash2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Info Hash v2:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="5">
|
||||
<widget class="QLabel" name="labelInfohash2Val">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -819,7 +835,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelSavePath">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
|
@ -835,7 +851,39 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="5">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelComment">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Comment:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="5">
|
||||
<widget class="QLabel" name="labelInfohash1Val">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="5">
|
||||
<widget class="QLabel" name="labelSavePathVal">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
|
@ -854,23 +902,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelComment">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Comment:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="5">
|
||||
<item row="5" column="1" colspan="5">
|
||||
<widget class="QLabel" name="labelCommentVal">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
|
|
|
@ -487,7 +487,33 @@ void TransferListWidget::copySelectedNames() const
|
|||
qApp->clipboard()->setText(torrentNames.join('\n'));
|
||||
}
|
||||
|
||||
void TransferListWidget::copySelectedHashes() const
|
||||
void TransferListWidget::copySelectedInfohashes(const CopyInfohashPolicy policy) const
|
||||
{
|
||||
const auto selectedTorrents = getSelectedTorrents();
|
||||
QStringList infoHashes;
|
||||
infoHashes.reserve(selectedTorrents.size());
|
||||
switch (policy)
|
||||
{
|
||||
case CopyInfohashPolicy::Version1:
|
||||
for (const BitTorrent::Torrent *torrent : selectedTorrents)
|
||||
{
|
||||
if (const auto infoHash = torrent->infoHash().v1(); infoHash.isValid())
|
||||
infoHashes << infoHash.toString();
|
||||
}
|
||||
break;
|
||||
case CopyInfohashPolicy::Version2:
|
||||
for (const BitTorrent::Torrent *torrent : selectedTorrents)
|
||||
{
|
||||
if (const auto infoHash = torrent->infoHash().v2(); infoHash.isValid())
|
||||
infoHashes << infoHash.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
qApp->clipboard()->setText(infoHashes.join('\n'));
|
||||
}
|
||||
|
||||
void TransferListWidget::copySelectedIDs() const
|
||||
{
|
||||
QStringList torrentIDs;
|
||||
for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents()))
|
||||
|
@ -827,10 +853,14 @@ void TransferListWidget::displayListMenu(const QPoint &)
|
|||
connect(actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents);
|
||||
auto *actionCopyMagnetLink = new QAction(UIThemeManager::instance()->getIcon("kt-magnet"), tr("Magnet link"), listMenu);
|
||||
connect(actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs);
|
||||
auto *actionCopyID = new QAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Torrent ID"), listMenu);
|
||||
connect(actionCopyID, &QAction::triggered, this, &TransferListWidget::copySelectedIDs);
|
||||
auto *actionCopyName = new QAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Name"), listMenu);
|
||||
connect(actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames);
|
||||
auto *actionCopyHash = new QAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Hash"), listMenu);
|
||||
connect(actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes);
|
||||
auto *actionCopyHash1 = new QAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Info hash v1"), listMenu);
|
||||
connect(actionCopyHash1, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version1); });
|
||||
auto *actionCopyHash2 = new QAction(UIThemeManager::instance()->getIcon("edit-copy"), tr("Info hash v2"), listMenu);
|
||||
connect(actionCopyHash2, &QAction::triggered, this, [this]() { copySelectedInfohashes(CopyInfohashPolicy::Version2); });
|
||||
auto *actionSuperSeedingMode = new TriStateAction(tr("Super seeding mode"), listMenu);
|
||||
connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSuperSeeding);
|
||||
auto *actionRename = new QAction(UIThemeManager::instance()->getIcon("edit-rename"), tr("Rename..."), listMenu);
|
||||
|
@ -860,6 +890,7 @@ void TransferListWidget::displayListMenu(const QPoint &)
|
|||
bool first = true;
|
||||
TagSet tagsInAny;
|
||||
TagSet tagsInAll;
|
||||
bool hasInfohashV1 = false, hasInfohashV2 = false;
|
||||
|
||||
for (const QModelIndex &index : selectedIndexes)
|
||||
{
|
||||
|
@ -939,12 +970,18 @@ void TransferListWidget::displayListMenu(const QPoint &)
|
|||
if (torrent->hasMetadata())
|
||||
needsPreview = true;
|
||||
|
||||
if (!hasInfohashV1 && torrent->infoHash().v1().isValid())
|
||||
hasInfohashV1 = true;
|
||||
if (!hasInfohashV2 && torrent->infoHash().v2().isValid())
|
||||
hasInfohashV2 = true;
|
||||
|
||||
first = false;
|
||||
|
||||
if (oneHasMetadata && oneNotSeed && !allSameSequentialDownloadMode
|
||||
&& !allSamePrioFirstlast && !allSameSuperSeeding && !allSameCategory
|
||||
&& needsStart && needsForce && needsPause && needsPreview && !allSameAutoTMM)
|
||||
{
|
||||
&& needsStart && needsForce && needsPause && needsPreview && !allSameAutoTMM
|
||||
&& hasInfohashV1 && hasInfohashV2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1084,8 +1121,12 @@ void TransferListWidget::displayListMenu(const QPoint &)
|
|||
QMenu *copySubMenu = listMenu->addMenu(
|
||||
UIThemeManager::instance()->getIcon("edit-copy"), tr("Copy"));
|
||||
copySubMenu->addAction(actionCopyName);
|
||||
copySubMenu->addAction(actionCopyHash);
|
||||
copySubMenu->addAction(actionCopyHash1);
|
||||
actionCopyHash1->setEnabled(hasInfohashV1);
|
||||
copySubMenu->addAction(actionCopyHash2);
|
||||
actionCopyHash2->setEnabled(hasInfohashV2);
|
||||
copySubMenu->addAction(actionCopyMagnetLink);
|
||||
copySubMenu->addAction(actionCopyID);
|
||||
|
||||
listMenu->popup(QCursor::pos());
|
||||
}
|
||||
|
|
|
@ -42,9 +42,16 @@ namespace BitTorrent
|
|||
class TorrentID;
|
||||
}
|
||||
|
||||
enum class CopyInfohashPolicy
|
||||
{
|
||||
Version1,
|
||||
Version2
|
||||
};
|
||||
|
||||
class TransferListWidget final : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(TransferListWidget)
|
||||
|
||||
public:
|
||||
TransferListWidget(QWidget *parent, MainWindow *mainWindow);
|
||||
|
@ -74,7 +81,8 @@ public slots:
|
|||
void bottomQueuePosSelectedTorrents();
|
||||
void copySelectedMagnetURIs() const;
|
||||
void copySelectedNames() const;
|
||||
void copySelectedHashes() const;
|
||||
void copySelectedInfohashes(CopyInfohashPolicy policy) const;
|
||||
void copySelectedIDs() const;
|
||||
void openSelectedTorrentsFolder() const;
|
||||
void recheckSelectedTorrents();
|
||||
void reannounceSelectedTorrents();
|
||||
|
@ -91,13 +99,10 @@ public slots:
|
|||
void previewFile(const QString &filePath);
|
||||
void renameSelectedTorrent();
|
||||
|
||||
protected:
|
||||
QModelIndex mapToSource(const QModelIndex &index) const;
|
||||
QModelIndex mapFromSource(const QModelIndex &index) const;
|
||||
bool loadSettings();
|
||||
QVector<BitTorrent::Torrent *> getSelectedTorrents() const;
|
||||
signals:
|
||||
void currentTorrentChanged(BitTorrent::Torrent *const torrent);
|
||||
|
||||
protected slots:
|
||||
private slots:
|
||||
void torrentDoubleClicked();
|
||||
void displayListMenu(const QPoint &);
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex&) override;
|
||||
|
@ -108,11 +113,12 @@ protected slots:
|
|||
void askNewCategoryForSelection();
|
||||
void saveSettings();
|
||||
|
||||
signals:
|
||||
void currentTorrentChanged(BitTorrent::Torrent *const torrent);
|
||||
|
||||
private:
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
QModelIndex mapToSource(const QModelIndex &index) const;
|
||||
QModelIndex mapFromSource(const QModelIndex &index) const;
|
||||
bool loadSettings();
|
||||
QVector<BitTorrent::Torrent *> getSelectedTorrents() const;
|
||||
void askAddTagsForSelection();
|
||||
void editTorrentTrackers();
|
||||
void confirmRemoveAllTagsForSelection();
|
||||
|
|
|
@ -96,8 +96,9 @@ QVariantMap serialize(const BitTorrent::Torrent &torrent)
|
|||
};
|
||||
|
||||
return {
|
||||
// TODO: Add fields for real SHA1 and SHA256 hashes
|
||||
{KEY_TORRENT_ID, QString(torrent.id().toString())},
|
||||
{KEY_TORRENT_ID, torrent.id().toString()},
|
||||
{KEY_TORRENT_INFOHASHV1, torrent.infoHash().v1().toString()},
|
||||
{KEY_TORRENT_INFOHASHV2, torrent.infoHash().v2().toString()},
|
||||
{KEY_TORRENT_NAME, torrent.name()},
|
||||
{KEY_TORRENT_MAGNET_URI, torrent.createMagnetURI()},
|
||||
{KEY_TORRENT_SIZE, torrent.wantedSize()},
|
||||
|
|
|
@ -36,7 +36,10 @@ namespace BitTorrent
|
|||
}
|
||||
|
||||
// Torrent keys
|
||||
// TODO: Rename it to `id`.
|
||||
inline const char KEY_TORRENT_ID[] = "hash";
|
||||
inline const char KEY_TORRENT_INFOHASHV1[] = "infohash_v1";
|
||||
inline const char KEY_TORRENT_INFOHASHV2[] = "infohash_v2";
|
||||
inline const char KEY_TORRENT_NAME[] = "name";
|
||||
inline const char KEY_TORRENT_MAGNET_URI[] = "magnet_uri";
|
||||
inline const char KEY_TORRENT_SIZE[] = "size";
|
||||
|
|
|
@ -382,6 +382,8 @@ void TorrentsController::propertiesAction()
|
|||
|
||||
QJsonObject dataDict;
|
||||
|
||||
dataDict[KEY_TORRENT_INFOHASHV1] = torrent->infoHash().v1().toString();
|
||||
dataDict[KEY_TORRENT_INFOHASHV2] = torrent->infoHash().v2().toString();
|
||||
dataDict[KEY_PROP_TIME_ELAPSED] = torrent->activeTime();
|
||||
dataDict[KEY_PROP_SEEDING_TIME] = torrent->seedingTime();
|
||||
dataDict[KEY_PROP_ETA] = static_cast<double>(torrent->eta());
|
||||
|
|
|
@ -166,8 +166,10 @@
|
|||
<a href="#" class="arrow-right"><img src="icons/edit-copy.svg" alt="QBT_TR(Copy)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Copy)QBT_TR[CONTEXT=TransferListWidget]</a>
|
||||
<ul>
|
||||
<li><a href="#" id="copyName" class="copyToClipboard"><img src="icons/edit-copy.svg" alt="QBT_TR(Name)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Name)QBT_TR[CONTEXT=TransferListWidget]</a></li>
|
||||
<li><a href="#" id="copyHash" class="copyToClipboard"><img src="icons/edit-copy.svg" alt="QBT_TR(Hash)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Hash)QBT_TR[CONTEXT=TransferListWidget]</a></li>
|
||||
<li><a href="#" id="copyInfohash1" class="copyToClipboard"><img src="icons/edit-copy.svg" alt="QBT_TR(Info hash v1)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Info hash v1)QBT_TR[CONTEXT=TransferListWidget]</a></li>
|
||||
<li><a href="#" id="copyInfohash2" class="copyToClipboard"><img src="icons/edit-copy.svg" alt="QBT_TR(Info hash v2)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Info hash v2)QBT_TR[CONTEXT=TransferListWidget]</a></li>
|
||||
<li><a href="#" id="copyMagnetLink" class="copyToClipboard"><img src="icons/kt-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="icons/edit-copy.svg" alt="QBT_TR(Torrent ID)QBT_TR[CONTEXT=TransferListWidget]" /> QBT_TR(Torrent ID)QBT_TR[CONTEXT=TransferListWidget]</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -1201,10 +1201,14 @@ function setupCopyEventHandler() {
|
|||
switch (trigger.id) {
|
||||
case "copyName":
|
||||
return copyNameFN();
|
||||
case "copyInfohash1":
|
||||
return copyInfohashFN(1);
|
||||
case "copyInfohash2":
|
||||
return copyInfohashFN(2);
|
||||
case "copyMagnetLink":
|
||||
return copyMagnetLinkFN();
|
||||
case "copyHash":
|
||||
return copyHashFN();
|
||||
case "copyID":
|
||||
return copyIdFN();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -1383,7 +1383,7 @@ window.qBittorrent.DynamicTable = (function() {
|
|||
tr.addClass("torrentsTableContextMenuTarget");
|
||||
},
|
||||
|
||||
getCurrentTorrentHash: function() {
|
||||
getCurrentTorrentID: function() {
|
||||
return this.getSelectedRowId();
|
||||
},
|
||||
|
||||
|
|
|
@ -84,8 +84,9 @@ let resumeTorrentsByTrackerFN = function() {};
|
|||
let pauseTorrentsByTrackerFN = function() {};
|
||||
let deleteTorrentsByTrackerFN = function() {};
|
||||
let copyNameFN = function() {};
|
||||
let copyInfohashFN = function(policy) {};
|
||||
let copyMagnetLinkFN = function() {};
|
||||
let copyHashFN = function() {};
|
||||
let copyIdFN = function() {};
|
||||
let setQueuePositionFN = function() {};
|
||||
|
||||
const initializeWindows = function() {
|
||||
|
@ -905,7 +906,7 @@ const initializeWindows = function() {
|
|||
copyNameFN = function() {
|
||||
const selectedRows = torrentsTable.selectedRowsIds();
|
||||
const names = [];
|
||||
if (selectedRows.length) {
|
||||
if (selectedRows.length > 0) {
|
||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||
for (let i = 0; i < selectedRows.length; ++i) {
|
||||
const hash = selectedRows[i];
|
||||
|
@ -915,10 +916,35 @@ const initializeWindows = function() {
|
|||
return names.join("\n");
|
||||
};
|
||||
|
||||
copyInfohashFN = function(policy) {
|
||||
const selectedRows = torrentsTable.selectedRowsIds();
|
||||
const infohashes = [];
|
||||
if (selectedRows.length > 0) {
|
||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||
switch (policy) {
|
||||
case 1:
|
||||
for (const id of selectedRows) {
|
||||
const infohash = rows[id].full_data.infohash_v1;
|
||||
if (infohash !== "")
|
||||
infohashes.push(infohash);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (const id of selectedRows) {
|
||||
const infohash = rows[id].full_data.infohash_v2;
|
||||
if (infohash !== "")
|
||||
infohashes.push(infohash);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return infohashes.join("\n");
|
||||
};
|
||||
|
||||
copyMagnetLinkFN = function() {
|
||||
const selectedRows = torrentsTable.selectedRowsIds();
|
||||
const magnets = [];
|
||||
if (selectedRows.length) {
|
||||
if (selectedRows.length > 0) {
|
||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||
for (let i = 0; i < selectedRows.length; ++i) {
|
||||
const hash = selectedRows[i];
|
||||
|
@ -928,7 +954,7 @@ const initializeWindows = function() {
|
|||
return magnets.join("\n");
|
||||
};
|
||||
|
||||
copyHashFN = function() {
|
||||
copyIdFN = function() {
|
||||
return torrentsTable.selectedRowsIds().join("\n");
|
||||
};
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ window.qBittorrent.PropFiles = (function() {
|
|||
// Tab changed, don't do anything
|
||||
return;
|
||||
}
|
||||
const new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
const new_hash = torrentsTable.getCurrentTorrentID();
|
||||
if (new_hash === "") {
|
||||
torrentFilesTable.clear();
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
|
@ -527,7 +527,7 @@ window.qBittorrent.PropFiles = (function() {
|
|||
menu: 'torrentFilesMenu',
|
||||
actions: {
|
||||
Rename: function(element, ref) {
|
||||
const hash = torrentsTable.getCurrentTorrentHash();
|
||||
const hash = torrentsTable.getCurrentTorrentID();
|
||||
if (!hash) return;
|
||||
const rowId = torrentFilesTable.selectedRowsIds()[0];
|
||||
if (rowId === undefined) return;
|
||||
|
|
|
@ -61,7 +61,8 @@ window.qBittorrent.PropGeneral = (function() {
|
|||
$('addition_date').set('html', '');
|
||||
$('completion_date').set('html', '');
|
||||
$('creation_date').set('html', '');
|
||||
$('torrent_hash').set('html', '');
|
||||
$('torrent_hash_v1').set('html', '');
|
||||
$('torrent_hash_v2').set('html', '');
|
||||
$('save_path').set('html', '');
|
||||
$('comment').set('html', '');
|
||||
};
|
||||
|
@ -73,16 +74,14 @@ window.qBittorrent.PropGeneral = (function() {
|
|||
// Tab changed, don't do anything
|
||||
return;
|
||||
}
|
||||
const current_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (current_hash === "") {
|
||||
const current_id = torrentsTable.getCurrentTorrentID();
|
||||
if (current_id === "") {
|
||||
clearData();
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||
return;
|
||||
}
|
||||
// Display hash
|
||||
$('torrent_hash').set('html', current_hash);
|
||||
const url = new URI('api/v2/torrents/properties?hash=' + current_hash);
|
||||
const url = new URI('api/v2/torrents/properties?hash=' + current_id);
|
||||
new Request.JSON({
|
||||
url: url,
|
||||
noCache: true,
|
||||
|
@ -191,6 +190,18 @@ window.qBittorrent.PropGeneral = (function() {
|
|||
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
||||
$('creation_date').set('html', temp);
|
||||
|
||||
if (data.infohash_v1 === "")
|
||||
temp = "QBT_TR(N/A)QBT_TR[CONTEXT=PropertiesWidget]";
|
||||
else
|
||||
temp = data.infohash_v1;
|
||||
$('torrent_hash_v1').set('html', temp);
|
||||
|
||||
if (data.infohash_v2 === "")
|
||||
temp = "QBT_TR(N/A)QBT_TR[CONTEXT=PropertiesWidget]";
|
||||
else
|
||||
temp = data.infohash_v2;
|
||||
$('torrent_hash_v2').set('html', temp);
|
||||
|
||||
$('save_path').set('html', data.save_path);
|
||||
|
||||
$('comment').set('html', window.qBittorrent.Misc.parseHtmlLinks(window.qBittorrent.Misc.escapeHtml(data.comment)));
|
||||
|
|
|
@ -51,7 +51,7 @@ window.qBittorrent.PropPeers = (function() {
|
|||
torrentPeersTable.clear();
|
||||
return;
|
||||
}
|
||||
const current_hash = torrentsTable.getCurrentTorrentHash();
|
||||
const current_hash = torrentsTable.getCurrentTorrentID();
|
||||
if (current_hash === "") {
|
||||
syncTorrentPeersLastResponseId = 0;
|
||||
torrentPeersTable.clear();
|
||||
|
@ -118,7 +118,7 @@ window.qBittorrent.PropPeers = (function() {
|
|||
menu: 'torrentPeersMenu',
|
||||
actions: {
|
||||
addPeer: function(element, ref) {
|
||||
const hash = torrentsTable.getCurrentTorrentHash();
|
||||
const hash = torrentsTable.getCurrentTorrentID();
|
||||
if (!hash)
|
||||
return;
|
||||
|
||||
|
@ -147,7 +147,7 @@ window.qBittorrent.PropPeers = (function() {
|
|||
noCache: true,
|
||||
method: 'post',
|
||||
data: {
|
||||
hash: torrentsTable.getCurrentTorrentHash(),
|
||||
hash: torrentsTable.getCurrentTorrentID(),
|
||||
peers: selectedPeers.join('|')
|
||||
}
|
||||
}).send();
|
||||
|
|
|
@ -50,7 +50,7 @@ window.qBittorrent.PropTrackers = (function() {
|
|||
// Tab changed, don't do anything
|
||||
return;
|
||||
}
|
||||
const new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
const new_hash = torrentsTable.getCurrentTorrentID();
|
||||
if (new_hash === "") {
|
||||
torrentTrackersTable.clear();
|
||||
clearTimeout(loadTrackersDataTimer);
|
||||
|
|
|
@ -100,7 +100,7 @@ window.qBittorrent.PropWebseeds = (function() {
|
|||
// Tab changed, don't do anything
|
||||
return;
|
||||
}
|
||||
const new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
const new_hash = torrentsTable.getCurrentTorrentID();
|
||||
if (new_hash === "") {
|
||||
wsTable.removeAllRows();
|
||||
clearTimeout(loadWebSeedsDataTimer);
|
||||
|
|
|
@ -209,7 +209,9 @@
|
|||
<li>QBT_TR(%C: Number of files)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%Z: Torrent size (bytes))QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%T: Current tracker)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%I: Info hash)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%I: Info hash v1)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%J: Info hash v2)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
<li>QBT_TR(%K: Torrent ID)QBT_TR[CONTEXT=OptionsDialog]</li>
|
||||
</ul>
|
||||
QBT_TR(Tip: Encapsulate parameter with quotation marks to avoid text being cut off at whitespace (e.g., "%N"))QBT_TR[CONTEXT=OptionsDialog]
|
||||
</div>
|
||||
|
|
|
@ -64,8 +64,12 @@
|
|||
<td id="creation_date"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="generalLabel">QBT_TR(Torrent Hash:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
<td colspan="5" id="torrent_hash"></td>
|
||||
<td class="generalLabel">QBT_TR(Info Hash v1:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
<td colspan="5" id="torrent_hash_v1"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="generalLabel">QBT_TR(Info Hash v2:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
<td colspan="5" id="torrent_hash_v2"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="generalLabel">QBT_TR(Save Path:)QBT_TR[CONTEXT=PropertiesWidget]</td>
|
||||
|
|
Loading…
Reference in a new issue