Backport changes to v5.0.x branch

PR #21241.
This commit is contained in:
Vladimir Golovnev 2024-09-12 08:42:52 +03:00 committed by GitHub
commit f9a2b02a8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 102 additions and 10 deletions

View file

@ -2711,8 +2711,39 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr
if (m_loadingTorrents.contains(id) || (infoHash.isHybrid() && m_loadingTorrents.contains(altID))) if (m_loadingTorrents.contains(id) || (infoHash.isHybrid() && m_loadingTorrents.contains(altID)))
return false; return false;
if (findTorrent(infoHash)) if (Torrent *torrent = findTorrent(infoHash))
{
// a duplicate torrent is being added
if (hasMetadata)
{
// Trying to set metadata to existing torrent in case if it has none
torrent->setMetadata(*source.info());
}
if (!isMergeTrackersEnabled())
{
LogMsg(tr("Detected an attempt to add a duplicate torrent. Existing torrent: %1. Result: %2")
.arg(torrent->name(), tr("Merging of trackers is disabled")));
return false;
}
const bool isPrivate = torrent->isPrivate() || (hasMetadata && source.info()->isPrivate());
if (isPrivate)
{
LogMsg(tr("Detected an attempt to add a duplicate torrent. Existing torrent: %1. Result: %2")
.arg(torrent->name(), tr("Trackers cannot be merged because it is a private torrent")));
return false;
}
// merge trackers and web seeds
torrent->addTrackers(source.trackers());
torrent->addUrlSeeds(source.urlSeeds());
LogMsg(tr("Detected an attempt to add a duplicate torrent. Existing torrent: %1. Result: %2")
.arg(torrent->name(), tr("Trackers are merged from new source")));
return false; return false;
}
// It looks illogical that we don't just use an existing handle, // It looks illogical that we don't just use an existing handle,
// but as previous experience has shown, it actually creates unnecessary // but as previous experience has shown, it actually creates unnecessary

View file

@ -43,7 +43,6 @@ class QSslSocket;
#else #else
class QTcpSocket; class QTcpSocket;
#endif #endif
class QTextCodec;
namespace Net namespace Net
{ {

View file

@ -195,10 +195,8 @@ void PiecesBar::paintEvent(QPaintEvent *)
if (!m_highlightedRegion.isNull()) if (!m_highlightedRegion.isNull())
{ {
QColor highlightColor {this->palette().color(QPalette::Active, QPalette::Highlight)};
highlightColor.setAlphaF(0.35f);
QRect targetHighlightRect {m_highlightedRegion.adjusted(borderWidth, borderWidth, borderWidth, height() - 2 * borderWidth)}; QRect targetHighlightRect {m_highlightedRegion.adjusted(borderWidth, borderWidth, borderWidth, height() - 2 * borderWidth)};
painter.fillRect(targetHighlightRect, highlightColor); painter.fillRect(targetHighlightRect, highlightedPieceColor());
} }
QPainterPath border; QPainterPath border;
@ -231,6 +229,13 @@ QColor PiecesBar::pieceColor() const
return palette().color(QPalette::Active, QPalette::Highlight); return palette().color(QPalette::Active, QPalette::Highlight);
} }
QColor PiecesBar::highlightedPieceColor() const
{
QColor col = palette().color(QPalette::Highlight).darker();
col.setAlphaF(0.35);
return col;
}
QColor PiecesBar::colorBoxBorderColor() const QColor PiecesBar::colorBoxBorderColor() const
{ {
return palette().color(QPalette::Active, QPalette::ToolTipText); return palette().color(QPalette::Active, QPalette::ToolTipText);

View file

@ -68,7 +68,9 @@ protected:
QColor backgroundColor() const; QColor backgroundColor() const;
QColor borderColor() const; QColor borderColor() const;
QColor pieceColor() const; QColor pieceColor() const;
QColor highlightedPieceColor() const;
QColor colorBoxBorderColor() const; QColor colorBoxBorderColor() const;
const QVector<QRgb> &pieceColors() const; const QVector<QRgb> &pieceColors() const;
// mix two colors by light model, ratio <0, 1> // mix two colors by light model, ratio <0, 1>

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2018-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -50,6 +50,19 @@
#include "searchsortmodel.h" #include "searchsortmodel.h"
#include "ui_searchjobwidget.h" #include "ui_searchjobwidget.h"
namespace
{
enum DataRole
{
LinkVisitedRole = Qt::UserRole + 100
};
QColor visitedRowColor()
{
return QApplication::palette().color(QPalette::Disabled, QPalette::WindowText);
}
}
SearchJobWidget::SearchJobWidget(SearchHandler *searchHandler, IGUIApplication *app, QWidget *parent) SearchJobWidget::SearchJobWidget(SearchHandler *searchHandler, IGUIApplication *app, QWidget *parent)
: GUIApplicationComponent(app, parent) : GUIApplicationComponent(app, parent)
, m_ui {new Ui::SearchJobWidget} , m_ui {new Ui::SearchJobWidget}
@ -158,6 +171,8 @@ SearchJobWidget::SearchJobWidget(SearchHandler *searchHandler, IGUIApplication *
connect(this, &QObject::destroyed, searchHandler, &QObject::deleteLater); connect(this, &QObject::destroyed, searchHandler, &QObject::deleteLater);
setStatusTip(statusText(m_status)); setStatusTip(statusText(m_status));
connect(UIThemeManager::instance(), &UIThemeManager::themeChanged, this, &SearchJobWidget::onUIThemeChanged);
} }
SearchJobWidget::~SearchJobWidget() SearchJobWidget::~SearchJobWidget()
@ -179,9 +194,31 @@ QHeaderView *SearchJobWidget::header() const
// Set the color of a row in data model // Set the color of a row in data model
void SearchJobWidget::setRowColor(int row, const QColor &color) void SearchJobWidget::setRowColor(int row, const QColor &color)
{ {
m_proxyModel->setDynamicSortFilter(false);
for (int i = 0; i < m_proxyModel->columnCount(); ++i) for (int i = 0; i < m_proxyModel->columnCount(); ++i)
m_proxyModel->setData(m_proxyModel->index(row, i), color, Qt::ForegroundRole); m_proxyModel->setData(m_proxyModel->index(row, i), color, Qt::ForegroundRole);
}
void SearchJobWidget::setRowVisited(const int row)
{
m_proxyModel->setDynamicSortFilter(false);
m_proxyModel->setData(m_proxyModel->index(row, 0), true, LinkVisitedRole);
setRowColor(row, visitedRowColor());
m_proxyModel->setDynamicSortFilter(true);
}
void SearchJobWidget::onUIThemeChanged()
{
m_proxyModel->setDynamicSortFilter(false);
for (int row = 0; row < m_proxyModel->rowCount(); ++row)
{
const QVariant userData = m_proxyModel->data(m_proxyModel->index(row, 0), LinkVisitedRole);
const bool isVisited = userData.toBool();
if (isVisited)
setRowColor(row, visitedRowColor());
}
m_proxyModel->setDynamicSortFilter(true); m_proxyModel->setDynamicSortFilter(true);
} }
@ -284,7 +321,8 @@ void SearchJobWidget::downloadTorrent(const QModelIndex &rowIndex, const AddTorr
, this, [this, option](const QString &source) { addTorrentToSession(source, option); }); , this, [this, option](const QString &source) { addTorrentToSession(source, option); });
connect(downloadHandler, &SearchDownloadHandler::downloadFinished, downloadHandler, &SearchDownloadHandler::deleteLater); connect(downloadHandler, &SearchDownloadHandler::downloadFinished, downloadHandler, &SearchDownloadHandler::deleteLater);
} }
setRowColor(rowIndex.row(), QApplication::palette().color(QPalette::LinkVisited));
setRowVisited(rowIndex.row());
} }
void SearchJobWidget::addTorrentToSession(const QString &source, const AddTorrentOption option) void SearchJobWidget::addTorrentToSession(const QString &source, const AddTorrentOption option)

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2018-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -113,8 +113,10 @@ private:
void fillFilterComboBoxes(); void fillFilterComboBoxes();
NameFilteringMode filteringMode() const; NameFilteringMode filteringMode() const;
QHeaderView *header() const; QHeaderView *header() const;
void setRowColor(int row, const QColor &color);
int visibleColumnsCount() const; int visibleColumnsCount() const;
void setRowColor(int row, const QColor &color);
void setRowVisited(int row);
void onUIThemeChanged();
void downloadTorrents(AddTorrentOption option = AddTorrentOption::Default); void downloadTorrents(AddTorrentOption option = AddTorrentOption::Default);
void openTorrentPages() const; void openTorrentPages() const;

View file

@ -70,6 +70,13 @@
<option value="FilesChecked">QBT_TR(Files checked)QBT_TR[CONTEXT=OptionsDialog]</option> <option value="FilesChecked">QBT_TR(Files checked)QBT_TR[CONTEXT=OptionsDialog]</option>
</select> </select>
</div> </div>
<fieldset class="settings">
<legend>QBT_TR(When duplicate torrent is being added)QBT_TR[CONTEXT=OptionsDialog]</legend>
<div class="formRow">
<input type="checkbox" id="mergeTrackersInput">
<label for="mergeTrackersInput">QBT_TR(Merge trackers to existing torrent)QBT_TR[CONTEXT=OptionsDialog]</label>
</div>
</fieldset>
<div class="formRow"> <div class="formRow">
<input type="checkbox" id="deletetorrentfileafter_checkbox" /> <input type="checkbox" id="deletetorrentfileafter_checkbox" />
<label for="deletetorrentfileafter_checkbox">QBT_TR(Delete .torrent files afterwards)QBT_TR[CONTEXT=OptionsDialog]</label> <label for="deletetorrentfileafter_checkbox">QBT_TR(Delete .torrent files afterwards)QBT_TR[CONTEXT=OptionsDialog]</label>
@ -145,6 +152,10 @@
<input type="checkbox" id="use_subcategories_checkbox" /> <input type="checkbox" id="use_subcategories_checkbox" />
<label for="use_subcategories_checkbox">QBT_TR(Use Subcategories)QBT_TR[CONTEXT=OptionsDialog]</label> <label for="use_subcategories_checkbox">QBT_TR(Use Subcategories)QBT_TR[CONTEXT=OptionsDialog]</label>
</div> </div>
<div class="formRow">
<input type="checkbox" id="categoryPathsManualModeCheckbox" title="QBT_TR(Resolve relative Save Path against appropriate Category path instead of Default one)QBT_TR[CONTEXT=OptionsDialog]">
<label for="categoryPathsManualModeCheckbox">QBT_TR(Use Category paths in Manual Mode)QBT_TR[CONTEXT=OptionsDialog]</label>
</div>
<table> <table>
<tr> <tr>
<td> <td>
@ -2033,6 +2044,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
break; break;
} }
$("stopConditionSelect").getChildren("option")[index].selected = true; $("stopConditionSelect").getChildren("option")[index].selected = true;
$("mergeTrackersInput").setProperty("checked", pref.merge_trackers);
$("deletetorrentfileafter_checkbox").setProperty("checked", pref.auto_delete_mode); $("deletetorrentfileafter_checkbox").setProperty("checked", pref.auto_delete_mode);
$("preallocateall_checkbox").setProperty("checked", pref.preallocate_all); $("preallocateall_checkbox").setProperty("checked", pref.preallocate_all);
@ -2045,6 +2057,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
$("save_path_changed_tmm_combobox").setProperty("value", pref.save_path_changed_tmm_enabled); $("save_path_changed_tmm_combobox").setProperty("value", pref.save_path_changed_tmm_enabled);
$("category_changed_tmm_combobox").setProperty("value", pref.category_changed_tmm_enabled); $("category_changed_tmm_combobox").setProperty("value", pref.category_changed_tmm_enabled);
$("use_subcategories_checkbox").setProperty("checked", pref.use_subcategories); $("use_subcategories_checkbox").setProperty("checked", pref.use_subcategories);
$("categoryPathsManualModeCheckbox").setProperty("checked", pref.use_category_paths_in_manual_mode);
$("savepath_text").setProperty("value", pref.save_path); $("savepath_text").setProperty("value", pref.save_path);
$("temppath_checkbox").setProperty("checked", pref.temp_path_enabled); $("temppath_checkbox").setProperty("checked", pref.temp_path_enabled);
$("temppath_text").setProperty("value", pref.temp_path); $("temppath_text").setProperty("value", pref.temp_path);
@ -2417,6 +2430,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
settings["add_to_top_of_queue"] = $("addToTopOfQueueCheckbox").getProperty("checked"); settings["add_to_top_of_queue"] = $("addToTopOfQueueCheckbox").getProperty("checked");
settings["add_stopped_enabled"] = $("dontstartdownloads_checkbox").getProperty("checked"); settings["add_stopped_enabled"] = $("dontstartdownloads_checkbox").getProperty("checked");
settings["torrent_stop_condition"] = $("stopConditionSelect").getSelected()[0].getProperty("value"); settings["torrent_stop_condition"] = $("stopConditionSelect").getSelected()[0].getProperty("value");
settings["merge_trackers"] = $("mergeTrackersInput").getProperty("checked");
settings["auto_delete_mode"] = Number($("deletetorrentfileafter_checkbox").getProperty("checked")); settings["auto_delete_mode"] = Number($("deletetorrentfileafter_checkbox").getProperty("checked"));
settings["preallocate_all"] = $("preallocateall_checkbox").getProperty("checked"); settings["preallocate_all"] = $("preallocateall_checkbox").getProperty("checked");
@ -2429,6 +2443,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
settings["save_path_changed_tmm_enabled"] = ($("save_path_changed_tmm_combobox").getProperty("value") === "true"); settings["save_path_changed_tmm_enabled"] = ($("save_path_changed_tmm_combobox").getProperty("value") === "true");
settings["category_changed_tmm_enabled"] = ($("category_changed_tmm_combobox").getProperty("value") === "true"); settings["category_changed_tmm_enabled"] = ($("category_changed_tmm_combobox").getProperty("value") === "true");
settings["use_subcategories"] = $("use_subcategories_checkbox").getProperty("checked"); settings["use_subcategories"] = $("use_subcategories_checkbox").getProperty("checked");
settings["use_category_paths_in_manual_mode"] = $("categoryPathsManualModeCheckbox").getProperty("checked");
settings["save_path"] = $("savepath_text").getProperty("value"); settings["save_path"] = $("savepath_text").getProperty("value");
settings["temp_path_enabled"] = $("temppath_checkbox").getProperty("checked"); settings["temp_path_enabled"] = $("temppath_checkbox").getProperty("checked");
settings["temp_path"] = $("temppath_text").getProperty("value"); settings["temp_path"] = $("temppath_text").getProperty("value");