From 623210df58b8d587caedbbec5b8d9ec4127f569f Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sat, 15 Jun 2019 22:21:26 +0800 Subject: [PATCH 1/8] Improve handleFileErrorAlert error message --- src/base/bittorrent/session.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 826b3719a..2cc9ad11b 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -4002,20 +4002,23 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p) void Session::handleFileErrorAlert(const lt::file_error_alert *p) { - qDebug() << Q_FUNC_INFO; - // NOTE: Check this function! TorrentHandle *const torrent = m_torrents.value(p->handle.info_hash()); - if (torrent) { - const InfoHash hash = torrent->hash(); - if (!m_recentErroredTorrents.contains(hash)) { - m_recentErroredTorrents.insert(hash); - const QString msg = QString::fromStdString(p->message()); - LogMsg(tr("An I/O error occurred, '%1' paused. %2").arg(torrent->name(), msg)); - emit fullDiskError(torrent, msg); - } + if (!torrent) + return; - m_recentErroredTorrentsTimer->start(); + const InfoHash hash = torrent->hash(); + + if (!m_recentErroredTorrents.contains(hash)) { + m_recentErroredTorrents.insert(hash); + + const QString msg = QString::fromStdString(p->message()); + LogMsg(tr("File error alert. Torrent: \"%1\". File: \"%2\". Reason: %3") + .arg(torrent->name(), p->filename(), msg) + , Log::WARNING); + emit fullDiskError(torrent, msg); } + + m_recentErroredTorrentsTimer->start(); } void Session::handlePortmapWarningAlert(const lt::portmap_error_alert *p) From 3b015db77d25deec45b77b8552b061dfe4e905ba Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 16 Jun 2019 16:55:58 +0800 Subject: [PATCH 2/8] Add comparison operators for ProxyConfiguration --- src/base/net/proxyconfigurationmanager.cpp | 23 +++++++++++++--------- src/base/net/proxyconfigurationmanager.h | 2 ++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/base/net/proxyconfigurationmanager.cpp b/src/base/net/proxyconfigurationmanager.cpp index 1255fc6c1..4867cd69f 100644 --- a/src/base/net/proxyconfigurationmanager.cpp +++ b/src/base/net/proxyconfigurationmanager.cpp @@ -41,15 +41,20 @@ const QString KEY_PASSWORD = SETTINGS_KEY("Password"); namespace { inline SettingsStorage *settings() { return SettingsStorage::instance(); } +} - inline bool isSameConfig(const Net::ProxyConfiguration &conf1, const Net::ProxyConfiguration &conf2) - { - return conf1.type == conf2.type - && conf1.ip == conf2.ip - && conf1.port == conf2.port - && conf1.username == conf2.username - && conf1.password == conf2.password; - } +bool Net::operator==(const ProxyConfiguration &left, const ProxyConfiguration &right) +{ + return (left.type == right.type) + && (left.ip == right.ip) + && (left.port == right.port) + && (left.username == right.username) + && (left.password == right.password); +} + +bool Net::operator!=(const ProxyConfiguration &left, const ProxyConfiguration &right) +{ + return !(left == right); } using namespace Net; @@ -97,7 +102,7 @@ ProxyConfiguration ProxyConfigurationManager::proxyConfiguration() const void ProxyConfigurationManager::setProxyConfiguration(const ProxyConfiguration &config) { - if (!isSameConfig(config, m_config)) { + if (config != m_config) { m_config = config; settings()->storeValue(KEY_TYPE, static_cast(config.type)); settings()->storeValue(KEY_IP, config.ip); diff --git a/src/base/net/proxyconfigurationmanager.h b/src/base/net/proxyconfigurationmanager.h index 87f1f88e9..c336cc8df 100644 --- a/src/base/net/proxyconfigurationmanager.h +++ b/src/base/net/proxyconfigurationmanager.h @@ -51,6 +51,8 @@ namespace Net QString username; QString password; }; + bool operator==(const ProxyConfiguration &left, const ProxyConfiguration &right); + bool operator!=(const ProxyConfiguration &left, const ProxyConfiguration &right); class ProxyConfigurationManager : public QObject { From a6c5a90630428689deeeccd45bec3b3acb89ff94 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 16 Jun 2019 17:50:55 +0800 Subject: [PATCH 3/8] Remove redundant variable --- src/base/bittorrent/session.cpp | 63 +++++++++++++++++---------------- src/base/bittorrent/session.h | 1 - 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 2cc9ad11b..75253f7b0 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -362,7 +362,6 @@ Session::Session(QObject *parent) , m_wasPexEnabled(m_isPeXEnabled) , m_numResumeData(0) , m_extraLimit(0) - , m_useProxy(false) , m_recentErroredTorrentsTimer(new QTimer(this)) { Logger *const logger = Logger::instance(); @@ -1211,42 +1210,44 @@ void Session::configure(lt::settings_pack &settingsPack) settingsPack.set_int(lt::settings_pack::in_enc_policy, lt::settings_pack::pe_disabled); } + // proxy const auto proxyManager = Net::ProxyConfigurationManager::instance(); const Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration(); - if (m_useProxy || (proxyConfig.type != Net::ProxyType::None)) { - if (proxyConfig.type != Net::ProxyType::None) { - settingsPack.set_str(lt::settings_pack::proxy_hostname, proxyConfig.ip.toStdString()); - settingsPack.set_int(lt::settings_pack::proxy_port, proxyConfig.port); - if (proxyManager->isAuthenticationRequired()) { - settingsPack.set_str(lt::settings_pack::proxy_username, proxyConfig.username.toStdString()); - settingsPack.set_str(lt::settings_pack::proxy_password, proxyConfig.password.toStdString()); - } - settingsPack.set_bool(lt::settings_pack::proxy_peer_connections, isProxyPeerConnectionsEnabled()); - } - switch (proxyConfig.type) { - case Net::ProxyType::HTTP: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http); - break; - case Net::ProxyType::HTTP_PW: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http_pw); - break; - case Net::ProxyType::SOCKS4: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks4); - break; - case Net::ProxyType::SOCKS5: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5); - break; - case Net::ProxyType::SOCKS5_PW: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5_pw); - break; - default: - settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::none); + switch (proxyConfig.type) { + case Net::ProxyType::HTTP: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http); + break; + case Net::ProxyType::HTTP_PW: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::http_pw); + break; + case Net::ProxyType::SOCKS4: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks4); + break; + case Net::ProxyType::SOCKS5: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5); + break; + case Net::ProxyType::SOCKS5_PW: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::socks5_pw); + break; + case Net::ProxyType::None: + default: + settingsPack.set_int(lt::settings_pack::proxy_type, lt::settings_pack::none); + } + + if (proxyConfig.type != Net::ProxyType::None) { + settingsPack.set_str(lt::settings_pack::proxy_hostname, proxyConfig.ip.toStdString()); + settingsPack.set_int(lt::settings_pack::proxy_port, proxyConfig.port); + + if (proxyManager->isAuthenticationRequired()) { + settingsPack.set_str(lt::settings_pack::proxy_username, proxyConfig.username.toStdString()); + settingsPack.set_str(lt::settings_pack::proxy_password, proxyConfig.password.toStdString()); } - m_useProxy = (proxyConfig.type != Net::ProxyType::None); + settingsPack.set_bool(lt::settings_pack::proxy_peer_connections, isProxyPeerConnectionsEnabled()); } - settingsPack.set_bool(lt::settings_pack::force_proxy, m_useProxy ? isForceProxyEnabled() : false); + settingsPack.set_bool(lt::settings_pack::force_proxy + , ((proxyConfig.type == Net::ProxyType::None) ? false : isForceProxyEnabled())); settingsPack.set_bool(lt::settings_pack::announce_to_all_trackers, announceToAllTrackers()); settingsPack.set_bool(lt::settings_pack::announce_to_all_tiers, announceToAllTiers()); diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index 16125f73e..6dfdaacc9 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -671,7 +671,6 @@ namespace BitTorrent QVector m_additionalTrackerList; QString m_resumeFolderPath; QFile m_resumeFolderLock; - bool m_useProxy; QTimer *m_refreshTimer; QTimer *m_seedingLimitTimer; From e83019bdfab7e734789ee48b644be2e186f93e79 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 11 Jun 2019 20:32:34 +0800 Subject: [PATCH 4/8] Set wheel event to accepted only if we handle it --- src/gui/properties/peerlistwidget.cpp | 4 ++-- src/gui/transferlistwidget.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index 5682b840c..883a18a09 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -455,10 +455,10 @@ void PeerListWidget::handleSortColumnChanged(int col) void PeerListWidget::wheelEvent(QWheelEvent *event) { - event->accept(); - if (event->modifiers() & Qt::ShiftModifier) { // Shift + scroll = horizontal scroll + event->accept(); + QWheelEvent scrollHEvent(event->pos(), event->globalPos(), event->delta(), event->buttons(), event->modifiers(), Qt::Horizontal); QTreeView::wheelEvent(&scrollHEvent); return; diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index aa121ca2b..e548780b5 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -1226,10 +1226,10 @@ bool TransferListWidget::loadSettings() void TransferListWidget::wheelEvent(QWheelEvent *event) { - event->accept(); - if (event->modifiers() & Qt::ShiftModifier) { // Shift + scroll = horizontal scroll + event->accept(); + QWheelEvent scrollHEvent(event->pos(), event->globalPos(), event->delta(), event->buttons(), event->modifiers(), Qt::Horizontal); QTreeView::wheelEvent(&scrollHEvent); return; From 19f50a363d66e221978bb5363c7adac53a3b163c Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 17 Jun 2019 11:56:27 +0800 Subject: [PATCH 5/8] Fix crash when removing phantom tags Normally a tag is stored in both session and torrent's fastresume. A phantom tag is a tag that is stored in fastresume but not in session. This crash can occur when user resets his config file and choose to remove tag from torrent. Closes #10569. --- src/gui/tagfiltermodel.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/tagfiltermodel.cpp b/src/gui/tagfiltermodel.cpp index d2a98615a..d816a9699 100644 --- a/src/gui/tagfiltermodel.cpp +++ b/src/gui/tagfiltermodel.cpp @@ -216,15 +216,15 @@ void TagFilterModel::torrentTagAdded(BitTorrent::TorrentHandle *const torrent, c void TagFilterModel::torrentTagRemoved(BitTorrent::TorrentHandle *const torrent, const QString &tag) { - Q_ASSERT(torrent->tags().count() >= 0); - if (torrent->tags().count() == 0) + if (torrent->tags().empty()) untaggedItem()->increaseTorrentsCount(); const int row = findRow(tag); - Q_ASSERT(isValidRow(row)); - TagModelItem &item = m_tagItems[row]; + if (row < 0) + return; + + m_tagItems[row].decreaseTorrentsCount(); - item.decreaseTorrentsCount(); const QModelIndex i = index(row, 0, QModelIndex()); emit dataChanged(i, i); } From 1de4c2497c039e151d0f8f1846bb4b590ef741b8 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 18 Jun 2019 22:59:41 +0800 Subject: [PATCH 6/8] Fix wrong "Time Active" value displayed Closes #9612. --- src/gui/transferlistdelegate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/transferlistdelegate.cpp b/src/gui/transferlistdelegate.cpp index 7a314310f..cfd0550c0 100644 --- a/src/gui/transferlistdelegate.cpp +++ b/src/gui/transferlistdelegate.cpp @@ -121,8 +121,8 @@ void TransferListDelegate::paint(QPainter *painter, const QStyleOptionViewItem & } break; case TransferListModel::TR_TIME_ELAPSED: { - const int elapsedTime = index.data().toInt(); - const int seedingTime = index.data(Qt::UserRole).toInt(); + const qlonglong elapsedTime = index.data().toLongLong(); + const qlonglong seedingTime = index.data(Qt::UserRole).toLongLong(); const QString txt = (seedingTime > 0) ? tr("%1 (seeded for %2)", "e.g. 4m39s (seeded for 3m10s)") .arg(Utils::Misc::userFriendlyDuration(elapsedTime) From 516c968373615245d9381ea9f2147eadad166012 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 18 Jun 2019 23:01:51 +0800 Subject: [PATCH 7/8] Support year unit in userFriendlyDuration() --- src/base/utils/misc.cpp | 28 ++++++++++++++----------- src/base/utils/misc.h | 2 +- src/gui/properties/propertieswidget.cpp | 2 +- src/gui/transferlistdelegate.cpp | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/base/utils/misc.cpp b/src/base/utils/misc.cpp index 3941bc28e..e9f089918 100644 --- a/src/base/utils/misc.cpp +++ b/src/base/utils/misc.cpp @@ -323,11 +323,11 @@ bool Utils::Misc::isPreviewable(const QString &extension) return multimediaExtensions.contains(extension.toUpper()); } -// Take a number of seconds and return an user-friendly -// time duration like "1d 2h 10m". -QString Utils::Misc::userFriendlyDuration(const qlonglong seconds) +QString Utils::Misc::userFriendlyDuration(const qlonglong seconds, const qlonglong maxCap) { - if ((seconds < 0) || (seconds >= MAX_ETA)) + if (seconds < 0) + return QString::fromUtf8(C_INFINITY); + if ((maxCap >= 0) && (seconds >= maxCap)) return QString::fromUtf8(C_INFINITY); if (seconds == 0) @@ -336,21 +336,25 @@ QString Utils::Misc::userFriendlyDuration(const qlonglong seconds) if (seconds < 60) return QCoreApplication::translate("misc", "< 1m", "< 1 minute"); - qlonglong minutes = seconds / 60; + qlonglong minutes = (seconds / 60); if (minutes < 60) return QCoreApplication::translate("misc", "%1m", "e.g: 10minutes").arg(QString::number(minutes)); - qlonglong hours = minutes / 60; - minutes -= hours * 60; - if (hours < 24) + qlonglong hours = (minutes / 60); + if (hours < 24) { + minutes -= (hours * 60); return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours), QString::number(minutes)); + } - qlonglong days = hours / 24; - hours -= days * 24; - if (days < 100) + qlonglong days = (hours / 24); + if (days < 365) { + hours -= (days * 24); return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days), QString::number(hours)); + } - return QString::fromUtf8(C_INFINITY); + qlonglong years = (days / 365); + days -= (years * 365); + return QCoreApplication::translate("misc", "%1y %2d", "e.g: 2years 10days").arg(QString::number(years), QString::number(days)); } QString Utils::Misc::getUserIDString() diff --git a/src/base/utils/misc.h b/src/base/utils/misc.h index c83918ed0..31e6fb3a7 100644 --- a/src/base/utils/misc.h +++ b/src/base/utils/misc.h @@ -84,7 +84,7 @@ namespace Utils // Take a number of seconds and return a user-friendly // time duration like "1d 2h 10m". - QString userFriendlyDuration(qlonglong seconds); + QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1); QString getUserIDString(); #ifdef Q_OS_WIN diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 196d2fa68..229eaf444 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -420,7 +420,7 @@ void PropertiesWidget::loadDynamicData() .arg(m_torrent->connectionsCount()) .arg(m_torrent->connectionsLimit() < 0 ? QString::fromUtf8(C_INFINITY) : QString::number(m_torrent->connectionsLimit()))); - m_ui->labelETAVal->setText(Utils::Misc::userFriendlyDuration(m_torrent->eta())); + m_ui->labelETAVal->setText(Utils::Misc::userFriendlyDuration(m_torrent->eta(), MAX_ETA)); // Update next announce time m_ui->labelReannounceInVal->setText(Utils::Misc::userFriendlyDuration(m_torrent->nextAnnounce())); diff --git a/src/gui/transferlistdelegate.cpp b/src/gui/transferlistdelegate.cpp index cfd0550c0..1ece77805 100644 --- a/src/gui/transferlistdelegate.cpp +++ b/src/gui/transferlistdelegate.cpp @@ -82,7 +82,7 @@ void TransferListDelegate::paint(QPainter *painter, const QStyleOptionViewItem & break; case TransferListModel::TR_ETA: { opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong())); + QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong(), MAX_ETA)); break; } case TransferListModel::TR_SEEDS: From 4880dc812ce2142f42a289e6f337a97bfd445982 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 18 Jun 2019 23:36:45 +0800 Subject: [PATCH 8/8] Use appropriate type --- src/base/bittorrent/session.cpp | 2 +- src/gui/properties/propertieswidget.cpp | 4 ++-- src/webui/api/torrentscontroller.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 75253f7b0..7f1292ef3 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -1532,7 +1532,7 @@ void Session::processShareLimits() } if (torrent->seedingTimeLimit() != TorrentHandle::NO_SEEDING_TIME_LIMIT) { - const int seedingTimeInMinutes = torrent->seedingTime() / 60; + const qlonglong seedingTimeInMinutes = torrent->seedingTime() / 60; int seedingTimeLimit = torrent->seedingTimeLimit(); if (seedingTimeLimit == TorrentHandle::USE_GLOBAL_SEEDING_TIME) // If Global Seeding Time Limit is really set... diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 229eaf444..daedec77f 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -437,12 +437,12 @@ void PropertiesWidget::loadDynamicData() .arg(QString::number(m_torrent->leechsCount()) , QString::number(m_torrent->totalLeechersCount()))); - const int dlDuration = m_torrent->activeTime() - m_torrent->finishedTime(); + const qlonglong dlDuration = m_torrent->activeTime() - m_torrent->finishedTime(); const QString dlAvg = Utils::Misc::friendlyUnit((m_torrent->totalDownload() / ((dlDuration == 0) ? -1 : dlDuration)), true); m_ui->labelDlSpeedVal->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)") .arg(Utils::Misc::friendlyUnit(m_torrent->downloadPayloadRate(), true), dlAvg)); - const int ulDuration = m_torrent->activeTime(); + const qlonglong ulDuration = m_torrent->activeTime(); const QString ulAvg = Utils::Misc::friendlyUnit((m_torrent->totalUpload() / ((ulDuration == 0) ? -1 : ulDuration)), true); m_ui->labelUpSpeedVal->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)") .arg(Utils::Misc::friendlyUnit(m_torrent->uploadPayloadRate(), true), ulAvg)); diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index 48d42bb22..7b6ae75ca 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -324,10 +324,10 @@ void TorrentsController::propertiesAction() dataDict[KEY_PROP_UPLOADED] = torrent->totalUpload(); dataDict[KEY_PROP_UPLOADED_SESSION] = torrent->totalPayloadUpload(); dataDict[KEY_PROP_DL_SPEED] = torrent->downloadPayloadRate(); - const int dlDuration = torrent->activeTime() - torrent->finishedTime(); + const qlonglong dlDuration = torrent->activeTime() - torrent->finishedTime(); dataDict[KEY_PROP_DL_SPEED_AVG] = torrent->totalDownload() / ((dlDuration == 0) ? -1 : dlDuration); dataDict[KEY_PROP_UP_SPEED] = torrent->uploadPayloadRate(); - const int ulDuration = torrent->activeTime(); + const qlonglong ulDuration = torrent->activeTime(); dataDict[KEY_PROP_UP_SPEED_AVG] = torrent->totalUpload() / ((ulDuration == 0) ? -1 : ulDuration); dataDict[KEY_PROP_DL_LIMIT] = torrent->downloadLimit() <= 0 ? -1 : torrent->downloadLimit(); dataDict[KEY_PROP_UP_LIMIT] = torrent->uploadLimit() <= 0 ? -1 : torrent->uploadLimit();