Browse Source

Merge pull request #4266 from naikel/seed_until

Share torrents until seeding time reaches an specific amount of minutes
adaptive-webui-19844
Vladimir Golovnev 8 years ago committed by GitHub
parent
commit
927ecc7075
  1. 2
      src/base/bittorrent/addtorrentparams.h
  2. 112
      src/base/bittorrent/session.cpp
  3. 12
      src/base/bittorrent/session.h
  4. 76
      src/base/bittorrent/torrenthandle.cpp
  5. 9
      src/base/bittorrent/torrenthandle.h
  6. 33
      src/gui/optionsdlg.cpp
  7. 2
      src/gui/optionsdlg.h
  8. 287
      src/gui/optionsdlg.ui
  9. 2
      src/gui/torrentcreatordlg.cpp
  10. 12
      src/gui/transferlistwidget.cpp
  11. 64
      src/gui/updownratiodlg.cpp
  12. 7
      src/gui/updownratiodlg.h
  13. 55
      src/gui/updownratiodlg.ui
  14. 1
      src/webui/extra_translations.h
  15. 6
      src/webui/prefjson.cpp
  16. 59
      src/webui/www/public/preferences_content.html

2
src/base/bittorrent/addtorrentparams.h

@ -46,7 +46,7 @@ namespace BitTorrent
TriStateBool addForced; TriStateBool addForced;
TriStateBool addPaused; TriStateBool addPaused;
QVector<int> filePriorities; // used if TorrentInfo is set QVector<int> filePriorities; // used if TorrentInfo is set
bool ignoreShareRatio = false; bool ignoreShareLimits = false;
bool skipChecking = false; bool skipChecking = false;
TriStateBool createSubfolder; TriStateBool createSubfolder;
}; };

112
src/base/bittorrent/session.cpp

@ -235,6 +235,7 @@ Session::Session(QObject *parent)
, m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false) , m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false)
, m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers")) , m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers"))
, m_globalMaxRatio(BITTORRENT_SESSION_KEY("GlobalMaxRatio"), -1, [](qreal r) { return r < 0 ? -1. : r;}) , m_globalMaxRatio(BITTORRENT_SESSION_KEY("GlobalMaxRatio"), -1, [](qreal r) { return r < 0 ? -1. : r;})
, m_globalMaxSeedingMinutes(BITTORRENT_SESSION_KEY("GlobalMaxSeedingMinutes"), -1, lowerLimited(-1))
, m_isAddTorrentPaused(BITTORRENT_SESSION_KEY("AddTorrentPaused"), false) , m_isAddTorrentPaused(BITTORRENT_SESSION_KEY("AddTorrentPaused"), false)
, m_isCreateTorrentSubfolder(BITTORRENT_SESSION_KEY("CreateTorrentSubfolder"), true) , m_isCreateTorrentSubfolder(BITTORRENT_SESSION_KEY("CreateTorrentSubfolder"), true)
, m_isAppendExtensionEnabled(BITTORRENT_SESSION_KEY("AddExtensionToIncompleteFiles"), false) , m_isAppendExtensionEnabled(BITTORRENT_SESSION_KEY("AddExtensionToIncompleteFiles"), false)
@ -287,9 +288,9 @@ Session::Session(QObject *parent)
initResumeFolder(); initResumeFolder();
m_bigRatioTimer = new QTimer(this); m_seedingLimitTimer = new QTimer(this);
m_bigRatioTimer->setInterval(10000); m_seedingLimitTimer->setInterval(10000);
connect(m_bigRatioTimer, SIGNAL(timeout()), SLOT(processBigRatios())); connect(m_seedingLimitTimer, SIGNAL(timeout()), SLOT(processShareLimits()));
// Set severity level of libtorrent session // Set severity level of libtorrent session
int alertMask = libt::alert::error_notification int alertMask = libt::alert::error_notification
@ -411,7 +412,7 @@ Session::Session(QObject *parent)
m_statistics = new Statistics(this); m_statistics = new Statistics(this);
updateRatioTimer(); updateSeedingLimitTimer();
populateAdditionalTrackers(); populateAdditionalTrackers();
enableTracker(isTrackerEnabled()); enableTracker(isTrackerEnabled());
@ -800,7 +801,23 @@ void Session::setGlobalMaxRatio(qreal ratio)
if (ratio != globalMaxRatio()) { if (ratio != globalMaxRatio()) {
m_globalMaxRatio = ratio; m_globalMaxRatio = ratio;
updateRatioTimer(); updateSeedingLimitTimer();
}
}
int Session::globalMaxSeedingMinutes() const
{
return m_globalMaxSeedingMinutes;
}
void Session::setGlobalMaxSeedingMinutes(int minutes)
{
if (minutes < 0)
minutes = -1;
if (minutes != globalMaxSeedingMinutes()) {
m_globalMaxSeedingMinutes = minutes;
updateSeedingLimitTimer();
} }
} }
@ -1415,36 +1432,56 @@ void Session::populateAdditionalTrackers()
} }
} }
void Session::processBigRatios() void Session::processShareLimits()
{ {
qDebug("Process big ratios..."); qDebug("Processing share limits...");
qreal globalMaxRatio = this->globalMaxRatio();
foreach (TorrentHandle *const torrent, m_torrents) { foreach (TorrentHandle *const torrent, m_torrents) {
if (torrent->isSeed() if (torrent->isSeed() && !torrent->isForced()) {
&& (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) {
&& !torrent->isForced()) {
const qreal ratio = torrent->realRatio(); const qreal ratio = torrent->realRatio();
qreal ratioLimit = torrent->ratioLimit(); qreal ratioLimit = torrent->ratioLimit();
if (ratioLimit == TorrentHandle::USE_GLOBAL_RATIO) { if (ratioLimit == TorrentHandle::USE_GLOBAL_RATIO)
// If Global Max Ratio is really set... // If Global Max Ratio is really set...
ratioLimit = globalMaxRatio; ratioLimit = globalMaxRatio();
if (ratioLimit < 0) continue;
} if (ratioLimit >= 0) {
qDebug("Ratio: %f (limit: %f)", ratio, ratioLimit); qDebug("Ratio: %f (limit: %f)", ratio, ratioLimit);
Q_ASSERT(ratioLimit >= 0.f);
if ((ratio <= TorrentHandle::MAX_RATIO) && (ratio >= ratioLimit)) { if ((ratio <= TorrentHandle::MAX_RATIO) && (ratio >= ratioLimit)) {
Logger* const logger = Logger::instance(); Logger* const logger = Logger::instance();
if (maxRatioAction() == Remove) { if (m_maxRatioAction == Remove) {
logger->addMessage(tr("'%1' reached the maximum ratio you set. Removing...").arg(torrent->name()));
deleteTorrent(torrent->hash()); deleteTorrent(torrent->hash());
logger->addMessage(tr("'%1' reached the maximum ratio you set. Removed.").arg(torrent->name()));
} }
else { else if (!torrent->isPaused()) {
// Pause it
if (!torrent->isPaused()) {
logger->addMessage(tr("'%1' reached the maximum ratio you set. Pausing...").arg(torrent->name()));
torrent->pause(); torrent->pause();
logger->addMessage(tr("'%1' reached the maximum ratio you set. Paused.").arg(torrent->name()));
}
}
}
}
if (torrent->seedingTimeLimit() != TorrentHandle::NO_SEEDING_TIME_LIMIT) {
const int seedingTimeInMinutes = torrent->seedingTime() / 60;
int seedingTimeLimit = torrent->seedingTimeLimit();
if (seedingTimeLimit == TorrentHandle::USE_GLOBAL_SEEDING_TIME)
// If Global Seeding Time Limit is really set...
seedingTimeLimit = globalMaxSeedingMinutes();
if (seedingTimeLimit >= 0) {
qDebug("Seeding Time: %d (limit: %d)", seedingTimeInMinutes, seedingTimeLimit);
if ((seedingTimeInMinutes <= TorrentHandle::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit)) {
Logger* const logger = Logger::instance();
if (m_maxRatioAction == Remove) {
deleteTorrent(torrent->hash());
logger->addMessage(tr("'%1' reached the maximum seeding time you set. Removed.").arg(torrent->name()));
}
else if (!torrent->isPaused()) {
torrent->pause();
logger->addMessage(tr("'%1' reached the maximum seeding time you set. Paused.").arg(torrent->name()));
}
} }
} }
} }
@ -2926,21 +2963,22 @@ bool Session::isKnownTorrent(const InfoHash &hash) const
|| m_loadedMetadata.contains(hash)); || m_loadedMetadata.contains(hash));
} }
void Session::updateRatioTimer() void Session::updateSeedingLimitTimer()
{ {
if ((globalMaxRatio() == -1) && !hasPerTorrentRatioLimit()) { if ((globalMaxRatio() == -1) && !hasPerTorrentRatioLimit()
if (m_bigRatioTimer->isActive()) && (globalMaxSeedingMinutes() == TorrentHandle::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit()) {
m_bigRatioTimer->stop(); if (m_seedingLimitTimer->isActive())
m_seedingLimitTimer->stop();
} }
else if (!m_bigRatioTimer->isActive()) { else if (!m_seedingLimitTimer->isActive()) {
m_bigRatioTimer->start(); m_seedingLimitTimer->start();
} }
} }
void Session::handleTorrentRatioLimitChanged(TorrentHandle *const torrent) void Session::handleTorrentShareLimitChanged(TorrentHandle *const torrent)
{ {
Q_UNUSED(torrent); Q_UNUSED(torrent);
updateRatioTimer(); updateSeedingLimitTimer();
} }
void Session::saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave) void Session::saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave)
@ -3119,6 +3157,14 @@ bool Session::hasPerTorrentRatioLimit() const
return false; return false;
} }
bool Session::hasPerTorrentSeedingTimeLimit() const
{
foreach (TorrentHandle *const torrent, m_torrents)
if (torrent->seedingTimeLimit() >= 0) return true;
return false;
}
void Session::initResumeFolder() void Session::initResumeFolder()
{ {
m_resumeFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + RESUME_FOLDER); m_resumeFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + RESUME_FOLDER);
@ -3528,8 +3574,9 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle)
saveTorrentResumeData(torrent); saveTorrentResumeData(torrent);
} }
if ((torrent->ratioLimit() >= 0) && !m_bigRatioTimer->isActive()) if (((torrent->ratioLimit() >= 0) || (torrent->seedingTimeLimit() >= 0))
m_bigRatioTimer->start(); && !m_seedingLimitTimer->isActive())
m_seedingLimitTimer->start();
// Send torrent addition signal // Send torrent addition signal
emit torrentAdded(torrent); emit torrentAdded(torrent);
@ -3875,6 +3922,7 @@ namespace
torrentData.savePath = Profile::instance().fromPortablePath( torrentData.savePath = Profile::instance().fromPortablePath(
Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath")))); Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath"))));
torrentData.ratioLimit = QString::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble(); torrentData.ratioLimit = QString::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble();
torrentData.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
// ************************************************************************************** // **************************************************************************************
// Workaround to convert legacy label to category // Workaround to convert legacy label to category
// TODO: Should be removed in future // TODO: Should be removed in future

12
src/base/bittorrent/session.h

@ -245,6 +245,8 @@ namespace BitTorrent
qreal globalMaxRatio() const; qreal globalMaxRatio() const;
void setGlobalMaxRatio(qreal ratio); void setGlobalMaxRatio(qreal ratio);
int globalMaxSeedingMinutes() const;
void setGlobalMaxSeedingMinutes(int minutes);
bool isDHTEnabled() const; bool isDHTEnabled() const;
void setDHTEnabled(bool enabled); void setDHTEnabled(bool enabled);
bool isLSDEnabled() const; bool isLSDEnabled() const;
@ -395,7 +397,7 @@ namespace BitTorrent
void bottomTorrentsPriority(const QStringList &hashes); void bottomTorrentsPriority(const QStringList &hashes);
// TorrentHandle interface // TorrentHandle interface
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent); void handleTorrentShareLimitChanged(TorrentHandle *const torrent);
void handleTorrentSavePathChanged(TorrentHandle *const torrent); void handleTorrentSavePathChanged(TorrentHandle *const torrent);
void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory); void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory);
void handleTorrentSavingModeChanged(TorrentHandle *const torrent); void handleTorrentSavingModeChanged(TorrentHandle *const torrent);
@ -455,7 +457,7 @@ namespace BitTorrent
void configureDeferred(); void configureDeferred();
void readAlerts(); void readAlerts();
void refresh(); void refresh();
void processBigRatios(); void processShareLimits();
void generateResumeData(bool final = false); void generateResumeData(bool final = false);
void handleIPFilterParsed(int ruleCount); void handleIPFilterParsed(int ruleCount);
void handleIPFilterError(); void handleIPFilterError();
@ -473,6 +475,7 @@ namespace BitTorrent
~Session(); ~Session();
bool hasPerTorrentRatioLimit() const; bool hasPerTorrentRatioLimit() const;
bool hasPerTorrentSeedingTimeLimit() const;
void initResumeFolder(); void initResumeFolder();
@ -503,7 +506,7 @@ namespace BitTorrent
const QByteArray &fastresumeData = QByteArray()); const QByteArray &fastresumeData = QByteArray());
bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const; bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const;
void updateRatioTimer(); void updateSeedingLimitTimer();
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular); void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
void saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave = false); void saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave = false);
@ -578,6 +581,7 @@ namespace BitTorrent
CachedSettingValue<bool> m_isAddTrackersEnabled; CachedSettingValue<bool> m_isAddTrackersEnabled;
CachedSettingValue<QString> m_additionalTrackers; CachedSettingValue<QString> m_additionalTrackers;
CachedSettingValue<qreal> m_globalMaxRatio; CachedSettingValue<qreal> m_globalMaxRatio;
CachedSettingValue<int> m_globalMaxSeedingMinutes;
CachedSettingValue<bool> m_isAddTorrentPaused; CachedSettingValue<bool> m_isAddTorrentPaused;
CachedSettingValue<bool> m_isCreateTorrentSubfolder; CachedSettingValue<bool> m_isCreateTorrentSubfolder;
CachedSettingValue<bool> m_isAppendExtensionEnabled; CachedSettingValue<bool> m_isAppendExtensionEnabled;
@ -628,7 +632,7 @@ namespace BitTorrent
bool m_useProxy; bool m_useProxy;
QTimer *m_refreshTimer; QTimer *m_refreshTimer;
QTimer *m_bigRatioTimer; QTimer *m_seedingLimitTimer;
QTimer *m_resumeDataTimer; QTimer *m_resumeDataTimer;
Statistics *m_statistics; Statistics *m_statistics;
// IP filtering // IP filtering

76
src/base/bittorrent/torrenthandle.cpp

@ -81,6 +81,7 @@ AddTorrentData::AddTorrentData()
, addForced(false) , addForced(false)
, addPaused(false) , addPaused(false)
, ratioLimit(TorrentHandle::USE_GLOBAL_RATIO) , ratioLimit(TorrentHandle::USE_GLOBAL_RATIO)
, seedingTimeLimit(TorrentHandle::USE_GLOBAL_SEEDING_TIME)
{ {
} }
@ -102,7 +103,8 @@ AddTorrentData::AddTorrentData(const AddTorrentParams &params)
? Session::instance()->isAddTorrentPaused() ? Session::instance()->isAddTorrentPaused()
: params.addPaused == TriStateBool::True) : params.addPaused == TriStateBool::True)
, filePriorities(params.filePriorities) , filePriorities(params.filePriorities)
, ratioLimit(params.ignoreShareRatio ? TorrentHandle::NO_RATIO_LIMIT : TorrentHandle::USE_GLOBAL_RATIO) , ratioLimit(params.ignoreShareLimits ? TorrentHandle::NO_RATIO_LIMIT : TorrentHandle::USE_GLOBAL_RATIO)
, seedingTimeLimit(params.ignoreShareLimits ? TorrentHandle::NO_SEEDING_TIME_LIMIT : TorrentHandle::USE_GLOBAL_SEEDING_TIME)
{ {
} }
@ -169,7 +171,11 @@ TorrentState::operator int() const
const qreal TorrentHandle::USE_GLOBAL_RATIO = -2.; const qreal TorrentHandle::USE_GLOBAL_RATIO = -2.;
const qreal TorrentHandle::NO_RATIO_LIMIT = -1.; const qreal TorrentHandle::NO_RATIO_LIMIT = -1.;
const int TorrentHandle::USE_GLOBAL_SEEDING_TIME = -2;
const int TorrentHandle::NO_SEEDING_TIME_LIMIT = -1;
const qreal TorrentHandle::MAX_RATIO = 9999.; const qreal TorrentHandle::MAX_RATIO = 9999.;
const int TorrentHandle::MAX_SEEDING_TIME = 525600;
// The new libtorrent::create_torrent constructor appeared after 1.0.11 in RC_1_0 // The new libtorrent::create_torrent constructor appeared after 1.0.11 in RC_1_0
// and after 1.1.1 in RC_1_1. Since it fixed an ABI incompatibility with previous versions // and after 1.1.1 in RC_1_1. Since it fixed an ABI incompatibility with previous versions
@ -209,6 +215,7 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
, m_category(data.category) , m_category(data.category)
, m_hasSeedStatus(data.hasSeedStatus) , m_hasSeedStatus(data.hasSeedStatus)
, m_ratioLimit(data.ratioLimit) , m_ratioLimit(data.ratioLimit)
, m_seedingTimeLimit(data.seedingTimeLimit)
, m_tempPathDisabled(data.disableTempPath) , m_tempPathDisabled(data.disableTempPath)
, m_hasMissingFiles(false) , m_hasMissingFiles(false)
, m_hasRootFolder(data.hasRootFolder) , m_hasRootFolder(data.hasRootFolder)
@ -581,6 +588,11 @@ qreal TorrentHandle::ratioLimit() const
return m_ratioLimit; return m_ratioLimit;
} }
int TorrentHandle::seedingTimeLimit() const
{
return m_seedingTimeLimit;
}
QString TorrentHandle::filePath(int index) const QString TorrentHandle::filePath(int index) const
{ {
return m_torrentInfo.filePath(index); return m_torrentInfo.filePath(index);
@ -907,24 +919,38 @@ qulonglong TorrentHandle::eta() const
{ {
if (isPaused()) return MAX_ETA; if (isPaused()) return MAX_ETA;
const SpeedSampleAvg speed_average = m_speedMonitor.average(); const SpeedSampleAvg speedAverage = m_speedMonitor.average();
if (isSeed()) { if (isSeed()) {
if (speed_average.upload == 0) return MAX_ETA; qreal maxRatioValue = maxRatio();
int maxSeedingTimeValue = maxSeedingTime();
if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0)) return MAX_ETA;
qlonglong ratioEta = MAX_ETA;
qreal max_ratio = maxRatio(); if ((speedAverage.upload > 0) && (maxRatioValue >= 0)) {
if (max_ratio < 0) return MAX_ETA;
qlonglong realDL = totalDownload(); qlonglong realDL = totalDownload();
if (realDL <= 0) if (realDL <= 0)
realDL = wantedSize(); realDL = wantedSize();
return ((realDL * max_ratio) - totalUpload()) / speed_average.upload; ratioEta = ((realDL * maxRatioValue) - totalUpload()) / speedAverage.upload;
}
qlonglong seedingTimeEta = MAX_ETA;
if (maxSeedingTimeValue >= 0) {
seedingTimeEta = (maxSeedingTimeValue * 60) - seedingTime();
if (seedingTimeEta < 0)
seedingTimeEta = 0;
}
return qMin(ratioEta, seedingTimeEta);
} }
if (!speed_average.download) return MAX_ETA; if (!speedAverage.download) return MAX_ETA;
return (wantedSize() - completedSize()) / speed_average.download; return (wantedSize() - completedSize()) / speedAverage.download;
} }
QVector<qreal> TorrentHandle::filesProgress() const QVector<qreal> TorrentHandle::filesProgress() const
@ -1105,6 +1131,23 @@ qreal TorrentHandle::maxRatio(bool *usesGlobalRatio) const
return ratioLimit; return ratioLimit;
} }
int TorrentHandle::maxSeedingTime(bool *usesGlobalSeedingTime) const
{
int seedingTimeLimit = m_seedingTimeLimit;
if (seedingTimeLimit == USE_GLOBAL_SEEDING_TIME) {
seedingTimeLimit = m_session->globalMaxSeedingMinutes();
if (usesGlobalSeedingTime)
*usesGlobalSeedingTime = true;
}
else {
if (usesGlobalSeedingTime)
*usesGlobalSeedingTime = false;
}
return seedingTimeLimit;
}
qreal TorrentHandle::realRatio() const qreal TorrentHandle::realRatio() const
{ {
boost::int64_t upload = m_nativeStatus.all_time_upload; boost::int64_t upload = m_nativeStatus.all_time_upload;
@ -1572,6 +1615,7 @@ void TorrentHandle::handleSaveResumeDataAlert(libtorrent::save_resume_data_alert
} }
resumeData["qBt-savePath"] = m_useAutoTMM ? "" : Profile::instance().toPortablePath(m_savePath).toStdString(); resumeData["qBt-savePath"] = m_useAutoTMM ? "" : Profile::instance().toPortablePath(m_savePath).toStdString();
resumeData["qBt-ratioLimit"] = QString::number(m_ratioLimit).toStdString(); resumeData["qBt-ratioLimit"] = QString::number(m_ratioLimit).toStdString();
resumeData["qBt-seedingTimeLimit"] = QString::number(m_seedingTimeLimit).toStdString();
resumeData["qBt-category"] = m_category.toStdString(); resumeData["qBt-category"] = m_category.toStdString();
resumeData["qBt-name"] = m_name.toStdString(); resumeData["qBt-name"] = m_name.toStdString();
resumeData["qBt-seedStatus"] = m_hasSeedStatus; resumeData["qBt-seedStatus"] = m_hasSeedStatus;
@ -1878,7 +1922,21 @@ void TorrentHandle::setRatioLimit(qreal limit)
if (m_ratioLimit != limit) { if (m_ratioLimit != limit) {
m_ratioLimit = limit; m_ratioLimit = limit;
m_needSaveResumeData = true; m_needSaveResumeData = true;
m_session->handleTorrentRatioLimitChanged(this); m_session->handleTorrentShareLimitChanged(this);
}
}
void TorrentHandle::setSeedingTimeLimit(int limit)
{
if (limit < USE_GLOBAL_SEEDING_TIME)
limit = NO_SEEDING_TIME_LIMIT;
else if (limit > MAX_SEEDING_TIME)
limit = MAX_SEEDING_TIME;
if (m_seedingTimeLimit != limit) {
m_seedingTimeLimit = limit;
m_needSaveResumeData = true;
m_session->handleTorrentShareLimitChanged(this);
} }
} }

9
src/base/bittorrent/torrenthandle.h

@ -106,6 +106,7 @@ namespace BitTorrent
QVector<int> filePriorities; QVector<int> filePriorities;
// for resumed torrents // for resumed torrents
qreal ratioLimit; qreal ratioLimit;
int seedingTimeLimit;
AddTorrentData(); AddTorrentData();
AddTorrentData(const AddTorrentParams &params); AddTorrentData(const AddTorrentParams &params);
@ -169,7 +170,11 @@ namespace BitTorrent
static const qreal USE_GLOBAL_RATIO; static const qreal USE_GLOBAL_RATIO;
static const qreal NO_RATIO_LIMIT; static const qreal NO_RATIO_LIMIT;
static const int USE_GLOBAL_SEEDING_TIME;
static const int NO_SEEDING_TIME_LIMIT;
static const qreal MAX_RATIO; static const qreal MAX_RATIO;
static const int MAX_SEEDING_TIME;
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle, TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
const AddTorrentData &data); const AddTorrentData &data);
@ -251,6 +256,7 @@ namespace BitTorrent
qreal progress() const; qreal progress() const;
QDateTime addedTime() const; QDateTime addedTime() const;
qreal ratioLimit() const; qreal ratioLimit() const;
int seedingTimeLimit() const;
QString filePath(int index) const; QString filePath(int index) const;
QString fileName(int index) const; QString fileName(int index) const;
@ -313,6 +319,7 @@ namespace BitTorrent
QVector<int> pieceAvailability() const; QVector<int> pieceAvailability() const;
qreal distributedCopies() const; qreal distributedCopies() const;
qreal maxRatio(bool *usesGlobalRatio = 0) const; qreal maxRatio(bool *usesGlobalRatio = 0) const;
int maxSeedingTime(bool *usesGlobalSeedingTime = 0) const;
qreal realRatio() const; qreal realRatio() const;
int uploadPayloadRate() const; int uploadPayloadRate() const;
int downloadPayloadRate() const; int downloadPayloadRate() const;
@ -341,6 +348,7 @@ namespace BitTorrent
void prioritizeFiles(const QVector<int> &priorities); void prioritizeFiles(const QVector<int> &priorities);
void setFilePriority(int index, int priority); void setFilePriority(int index, int priority);
void setRatioLimit(qreal limit); void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit);
void setUploadLimit(int limit); void setUploadLimit(int limit);
void setDownloadLimit(int limit); void setDownloadLimit(int limit);
void setSuperSeeding(bool enable); void setSuperSeeding(bool enable);
@ -439,6 +447,7 @@ namespace BitTorrent
QString m_category; QString m_category;
bool m_hasSeedStatus; bool m_hasSeedStatus;
qreal m_ratioLimit; qreal m_ratioLimit;
int m_seedingTimeLimit;
bool m_tempPathDisabled; bool m_tempPathDisabled;
bool m_hasMissingFiles; bool m_hasMissingFiles;
bool m_hasRootFolder; bool m_hasRootFolder;

33
src/gui/optionsdlg.cpp

@ -298,9 +298,14 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->checkLSD, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkLSD, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->comboEncryption, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboEncryption, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkMaxRatio, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkMaxRatio, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkMaxRatio, &QAbstractButton::toggled, this, &ThisType::toggleComboRatioLimitAct);
connect(m_ui->spinMaxRatio, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), connect(m_ui->spinMaxRatio, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &ThisType::enableApplyButton); this, &ThisType::enableApplyButton);
connect(m_ui->comboRatioLimitAct, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboRatioLimitAct, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkMaxSeedingMinutes, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkMaxSeedingMinutes, &QAbstractButton::toggled, this, &ThisType::toggleComboRatioLimitAct);
connect(m_ui->spinMaxSeedingMinutes, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
this, &ThisType::enableApplyButton);
// Proxy tab // Proxy tab
connect(m_ui->comboProxyType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboProxyType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textProxyIP, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); connect(m_ui->textProxyIP, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
@ -601,6 +606,7 @@ void OptionsDialog::saveOptions()
session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked());
session->setAdditionalTrackers(m_ui->textTrackers->toPlainText()); session->setAdditionalTrackers(m_ui->textTrackers->toPlainText());
session->setGlobalMaxRatio(getMaxRatio()); session->setGlobalMaxRatio(getMaxRatio());
session->setGlobalMaxSeedingMinutes(getMaxSeedingMinutes());
session->setMaxRatioAction(static_cast<MaxRatioAction>(m_ui->comboRatioLimitAct->currentIndex())); session->setMaxRatioAction(static_cast<MaxRatioAction>(m_ui->comboRatioLimitAct->currentIndex()));
// End Bittorrent preferences // End Bittorrent preferences
@ -990,8 +996,19 @@ void OptionsDialog::loadOptions()
// Disable // Disable
m_ui->checkMaxRatio->setChecked(false); m_ui->checkMaxRatio->setChecked(false);
m_ui->spinMaxRatio->setEnabled(false); m_ui->spinMaxRatio->setEnabled(false);
m_ui->comboRatioLimitAct->setEnabled(false);
} }
if (session->globalMaxSeedingMinutes() >= 0) {
// Enable
m_ui->checkMaxSeedingMinutes->setChecked(true);
m_ui->spinMaxSeedingMinutes->setEnabled(true);
m_ui->spinMaxSeedingMinutes->setValue(session->globalMaxSeedingMinutes());
}
else {
// Disable
m_ui->checkMaxSeedingMinutes->setChecked(false);
m_ui->spinMaxSeedingMinutes->setEnabled(false);
}
m_ui->comboRatioLimitAct->setEnabled((session->globalMaxSeedingMinutes() >= 0) || (session->globalMaxRatio() >= 0.));
m_ui->comboRatioLimitAct->setCurrentIndex(session->maxRatioAction()); m_ui->comboRatioLimitAct->setCurrentIndex(session->maxRatioAction());
// End Bittorrent preferences // End Bittorrent preferences
@ -1122,6 +1139,14 @@ qreal OptionsDialog::getMaxRatio() const
return -1; return -1;
} }
// Return Seeding Minutes
int OptionsDialog::getMaxSeedingMinutes() const
{
if (m_ui->checkMaxSeedingMinutes->isChecked())
return m_ui->spinMaxSeedingMinutes->value();
return -1;
}
// Return max connections number // Return max connections number
int OptionsDialog::getMaxConnecs() const int OptionsDialog::getMaxConnecs() const
{ {
@ -1211,6 +1236,12 @@ void OptionsDialog::enableApplyButton()
applyButton->setEnabled(true); applyButton->setEnabled(true);
} }
void OptionsDialog::toggleComboRatioLimitAct()
{
// Verify if the share action button must be enabled
m_ui->comboRatioLimitAct->setEnabled(m_ui->checkMaxRatio->isChecked() || m_ui->checkMaxSeedingMinutes->isChecked());
}
void OptionsDialog::enableProxy(int index) void OptionsDialog::enableProxy(int index)
{ {
if (index) { if (index) {

2
src/gui/optionsdlg.h

@ -90,6 +90,7 @@ private slots:
void on_buttonBox_rejected(); void on_buttonBox_rejected();
void applySettings(QAbstractButton* button); void applySettings(QAbstractButton* button);
void enableApplyButton(); void enableApplyButton();
void toggleComboRatioLimitAct();
void changePage(QListWidgetItem*, QListWidgetItem*); void changePage(QListWidgetItem*, QListWidgetItem*);
void loadWindowState(); void loadWindowState();
void saveWindowState() const; void saveWindowState() const;
@ -145,6 +146,7 @@ private:
bool isLSDEnabled() const; bool isLSDEnabled() const;
int getEncryptionSetting() const; int getEncryptionSetting() const;
qreal getMaxRatio() const; qreal getMaxRatio() const;
int getMaxSeedingMinutes() const;
// Proxy options // Proxy options
bool isProxyEnabled() const; bool isProxyEnabled() const;
bool isProxyAuthEnabled() const; bool isProxyAuthEnabled() const;

287
src/gui/optionsdlg.ui

@ -1852,9 +1852,6 @@
<property name="wrapping"> <property name="wrapping">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="displayFormat">
<string notr="true">hh:mm</string>
</property>
<property name="time"> <property name="time">
<time> <time>
<hour>20</hour> <hour>20</hour>
@ -1862,6 +1859,9 @@
<second>0</second> <second>0</second>
</time> </time>
</property> </property>
<property name="displayFormat">
<string notr="true">hh:mm</string>
</property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="0" column="2">
@ -1876,12 +1876,6 @@
<property name="wrapping"> <property name="wrapping">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="displayFormat">
<string notr="true">hh:mm</string>
</property>
<property name="calendarPopup">
<bool>false</bool>
</property>
<property name="time"> <property name="time">
<time> <time>
<hour>8</hour> <hour>8</hour>
@ -1889,6 +1883,12 @@
<second>0</second> <second>0</second>
</time> </time>
</property> </property>
<property name="displayFormat">
<string notr="true">hh:mm</string>
</property>
<property name="calendarPopup">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
@ -2374,20 +2374,110 @@
<property name="title"> <property name="title">
<string>Share Ratio Limiting</string> <string>Share Ratio Limiting</string>
</property> </property>
<layout class="QVBoxLayout"> <layout class="QGridLayout" name="gridLayout_91">
<property name="bottomMargin"> <item row="0" column="0" rowspan="3" colspan="3">
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QCheckBox" name="checkMaxRatio"> <widget class="QCheckBox" name="checkMaxRatio">
<property name="text"> <property name="text">
<string>Seed torrents until their ratio reaches</string> <string>Seed torrents until their ratio reaches</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="6" rowspan="2">
<spacer name="horizontalSpacer_161">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>109</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label">
<property name="text">
<string>then</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="4" colspan="2">
<widget class="QComboBox" name="comboRatioLimitAct">
<property name="enabled">
<bool>false</bool>
</property>
<item> <item>
<property name="text">
<string>Pause them</string>
</property>
</item>
<item>
<property name="text">
<string>Remove them</string>
</property>
</item>
</widget>
</item>
<item row="5" column="6">
<spacer name="horizontalSpacer_20">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>121</width>
<height>28</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<spacer name="horizontalSpacer_171">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>100</width>
<height>42</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="6">
<spacer name="horizontalSpacer_191">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="4">
<widget class="QSpinBox" name="spinMaxSeedingMinutes">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="maximum">
<number>9999999</number>
</property>
<property name="value">
<number>1440</number>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QDoubleSpinBox" name="spinMaxRatio"> <widget class="QDoubleSpinBox" name="spinMaxRatio">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@ -2409,33 +2499,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="3" column="5">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_11">
<property name="text"> <property name="text">
<string>then</string> <string>minutes</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="3" column="0" colspan="4">
<widget class="QComboBox" name="comboRatioLimitAct"> <widget class="QCheckBox" name="checkMaxSeedingMinutes">
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text"> <property name="text">
<string>Pause them</string> <string>Seed torrents until their seeding time reaches</string>
</property> </property>
</item>
<item>
<property name="text">
<string>Remove them</string>
</property>
</item>
</widget> </widget>
</item> </item>
</layout> </layout>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@ -2506,7 +2584,7 @@
<item> <item>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_11"> <widget class="QLabel" name="label_111">
<property name="text"> <property name="text">
<string>Feeds refresh interval:</string> <string>Feeds refresh interval:</string>
</property> </property>
@ -3035,16 +3113,129 @@
<tabstops> <tabstops>
<tabstop>tabOption</tabstop> <tabstop>tabOption</tabstop>
<tabstop>comboI18n</tabstop> <tabstop>comboI18n</tabstop>
<tabstop>browseSaveDirButton</tabstop>
<tabstop>checkStartPaused</tabstop> <tabstop>checkStartPaused</tabstop>
<tabstop>spinPort</tabstop> <tabstop>spinPort</tabstop>
<tabstop>checkUPnP</tabstop> <tabstop>checkUPnP</tabstop>
<tabstop>textWebUiUsername</tabstop>
<tabstop>checkWebUi</tabstop>
<tabstop>textSavePath</tabstop>
<tabstop>scrollArea_7</tabstop>
<tabstop>scrollArea_2</tabstop>
<tabstop>spinWebUiPort</tabstop>
<tabstop>textWebUiPassword</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>tabSelection</tabstop>
<tabstop>scrollArea</tabstop>
<tabstop>confirmDeletion</tabstop>
<tabstop>checkAltRowColors</tabstop>
<tabstop>actionTorrentDlOnDblClBox</tabstop>
<tabstop>actionTorrentFnOnDblClBox</tabstop>
<tabstop>checkStartup</tabstop>
<tabstop>checkShowSplash</tabstop>
<tabstop>checkStartMinimized</tabstop>
<tabstop>checkProgramExitConfirm</tabstop>
<tabstop>checkShowSystray</tabstop>
<tabstop>checkMinimizeToSysTray</tabstop>
<tabstop>checkCloseToSystray</tabstop>
<tabstop>comboTrayIcon</tabstop>
<tabstop>checkAssociateTorrents</tabstop>
<tabstop>checkAssociateMagnetLinks</tabstop>
<tabstop>checkPreventFromSuspend</tabstop>
<tabstop>checkAdditionDialog</tabstop>
<tabstop>checkAdditionDialogFront</tabstop>
<tabstop>checkPreallocateAll</tabstop>
<tabstop>checkTempFolder</tabstop>
<tabstop>textTempPath</tabstop>
<tabstop>browseTempDirButton</tabstop>
<tabstop>checkAppendqB</tabstop>
<tabstop>scanFoldersView</tabstop>
<tabstop>addScanFolderButton</tabstop>
<tabstop>removeScanFolderButton</tabstop>
<tabstop>checkExportDir</tabstop>
<tabstop>textExportDir</tabstop>
<tabstop>browseExportDirButton</tabstop>
<tabstop>checkExportDirFin</tabstop>
<tabstop>textExportDirFin</tabstop>
<tabstop>browseExportDirFinButton</tabstop>
<tabstop>groupMailNotification</tabstop>
<tabstop>dest_email_txt</tabstop>
<tabstop>smtp_server_txt</tabstop>
<tabstop>groupMailNotifAuth</tabstop>
<tabstop>mailNotifUsername</tabstop>
<tabstop>mailNotifPassword</tabstop>
<tabstop>checkSmtpSSL</tabstop>
<tabstop>autoRunBox</tabstop>
<tabstop>autoRun_txt</tabstop>
<tabstop>scrollArea_3</tabstop>
<tabstop>randomButton</tabstop>
<tabstop>checkRandomPort</tabstop>
<tabstop>checkMaxConnecs</tabstop>
<tabstop>spinMaxConnec</tabstop>
<tabstop>checkMaxConnecsPerTorrent</tabstop>
<tabstop>spinMaxConnecPerTorrent</tabstop>
<tabstop>checkMaxUploadsPerTorrent</tabstop>
<tabstop>spinMaxUploadsPerTorrent</tabstop>
<tabstop>checkMaxUploads</tabstop>
<tabstop>spinMaxUploads</tabstop>
<tabstop>comboProxyType</tabstop>
<tabstop>textProxyIP</tabstop>
<tabstop>spinProxyPort</tabstop>
<tabstop>checkProxyPeerConnecs</tabstop>
<tabstop>checkForceProxy</tabstop>
<tabstop>isProxyOnlyForTorrents</tabstop>
<tabstop>checkProxyAuth</tabstop>
<tabstop>textProxyUsername</tabstop>
<tabstop>textProxyPassword</tabstop>
<tabstop>checkIPFilter</tabstop>
<tabstop>textFilterPath</tabstop>
<tabstop>browseFilterButton</tabstop>
<tabstop>IpFilterRefreshBtn</tabstop>
<tabstop>checkIpFilterTrackers</tabstop>
<tabstop>scrollArea_9</tabstop>
<tabstop>spinUploadLimit</tabstop>
<tabstop>checkUploadLimit</tabstop>
<tabstop>spinDownloadLimit</tabstop>
<tabstop>checkDownloadLimit</tabstop>
<tabstop>check_schedule</tabstop>
<tabstop>schedule_to</tabstop>
<tabstop>schedule_from</tabstop>
<tabstop>schedule_days</tabstop>
<tabstop>checkUploadLimitAlt</tabstop>
<tabstop>checkDownloadLimitAlt</tabstop>
<tabstop>spinUploadLimitAlt</tabstop>
<tabstop>spinDownloadLimitAlt</tabstop>
<tabstop>checkLimitLocalPeerRate</tabstop>
<tabstop>checkLimitTransportOverhead</tabstop>
<tabstop>checkuTP</tabstop>
<tabstop>checkLimituTPConnections</tabstop>
<tabstop>scrollArea_4</tabstop>
<tabstop>checkDHT</tabstop>
<tabstop>checkPeX</tabstop>
<tabstop>checkLSD</tabstop> <tabstop>checkLSD</tabstop>
<tabstop>comboEncryption</tabstop> <tabstop>comboEncryption</tabstop>
<tabstop>checkAnonymousMode</tabstop>
<tabstop>checkEnableQueueing</tabstop>
<tabstop>spinMaxActiveDownloads</tabstop>
<tabstop>spinMaxActiveUploads</tabstop>
<tabstop>spinMaxActiveTorrents</tabstop>
<tabstop>checkIgnoreSlowTorrentsForQueueing</tabstop>
<tabstop>checkMaxRatio</tabstop> <tabstop>checkMaxRatio</tabstop>
<tabstop>spinMaxRatio</tabstop> <tabstop>spinMaxRatio</tabstop>
<tabstop>spinWebUiPort</tabstop> <tabstop>checkMaxSeedingMinutes</tabstop>
<tabstop>textWebUiUsername</tabstop> <tabstop>spinMaxSeedingMinutes</tabstop>
<tabstop>textWebUiPassword</tabstop> <tabstop>comboRatioLimitAct</tabstop>
<tabstop>checkWebUIUPnP</tabstop>
<tabstop>checkWebUiHttps</tabstop>
<tabstop>btnWebUiCrt</tabstop>
<tabstop>btnWebUiKey</tabstop>
<tabstop>checkBypassLocalAuth</tabstop>
<tabstop>checkDynDNS</tabstop>
<tabstop>comboDNSService</tabstop>
<tabstop>registerDNSBtn</tabstop>
<tabstop>domainNameTxt</tabstop>
<tabstop>DNSUsernameTxt</tabstop>
<tabstop>DNSPasswordTxt</tabstop>
</tabstops> </tabstops>
<resources> <resources>
<include location="../icons.qrc"/> <include location="../icons.qrc"/>
@ -3131,9 +3322,9 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>checkMaxRatio</sender> <sender>checkMaxUploads</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>spinMaxRatio</receiver> <receiver>spinMaxUploads</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -3147,9 +3338,9 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>checkMaxRatio</sender> <sender>checkDownloadLimitAlt</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>comboRatioLimitAct</receiver> <receiver>spinDownloadLimitAlt</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -3163,9 +3354,9 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>checkMaxUploads</sender> <sender>checkUploadLimitAlt</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>spinMaxUploads</receiver> <receiver>spinUploadLimitAlt</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -3179,9 +3370,9 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>checkDownloadLimitAlt</sender> <sender>checkMaxRatio</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>spinDownloadLimitAlt</receiver> <receiver>spinMaxRatio</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -3195,9 +3386,9 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>checkUploadLimitAlt</sender> <sender>checkMaxSeedingMinutes</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>spinUploadLimitAlt</receiver> <receiver>spinMaxSeedingMinutes</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

2
src/gui/torrentcreatordlg.cpp

@ -169,7 +169,7 @@ void TorrentCreatorDlg::handleCreationSuccess(QString path, QString branch_path)
BitTorrent::AddTorrentParams params; BitTorrent::AddTorrentParams params;
params.savePath = branch_path; params.savePath = branch_path;
params.skipChecking = true; params.skipChecking = true;
params.ignoreShareRatio = checkIgnoreShareLimits->isChecked(); params.ignoreShareLimits = checkIgnoreShareLimits->isChecked();
BitTorrent::Session::instance()->addTorrent(t, params); BitTorrent::Session::instance()->addTorrent(t, params);
} }

12
src/gui/transferlistwidget.cpp

@ -487,16 +487,24 @@ void TransferListWidget::setMaxRatioSelectedTorrents()
if (torrents.isEmpty()) return; if (torrents.isEmpty()) return;
bool useGlobalValue = true; bool useGlobalValue = true;
qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();; qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();
if (torrents.count() == 1) if (torrents.count() == 1)
currentMaxRatio = torrents[0]->maxRatio(&useGlobalValue); currentMaxRatio = torrents[0]->maxRatio(&useGlobalValue);
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, this); int currentMaxSeedingTime = BitTorrent::Session::instance()->globalMaxSeedingMinutes();
if (torrents.count() == 1)
currentMaxSeedingTime = torrents[0]->maxSeedingTime(&useGlobalValue);
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO,
currentMaxSeedingTime, BitTorrent::TorrentHandle::MAX_SEEDING_TIME, this);
if (dlg.exec() != QDialog::Accepted) return; if (dlg.exec() != QDialog::Accepted) return;
foreach (BitTorrent::TorrentHandle *const torrent, torrents) { foreach (BitTorrent::TorrentHandle *const torrent, torrents) {
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio()); qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
torrent->setRatioLimit(ratio); torrent->setRatioLimit(ratio);
int seedingTime = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_SEEDING_TIME : dlg.seedingTime());
torrent->setSeedingTimeLimit(seedingTime);
} }
} }

64
src/gui/updownratiodlg.cpp

@ -30,11 +30,15 @@
#include "updownratiodlg.h" #include "updownratiodlg.h"
#include <QMessageBox>
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "ui_updownratiodlg.h" #include "ui_updownratiodlg.h"
UpDownRatioDlg::UpDownRatioDlg(bool useDefault, qreal initialValue, UpDownRatioDlg::UpDownRatioDlg(bool useDefault, qreal initialRatioValue,
qreal maxValue, QWidget *parent) qreal maxRatioValue, int initialTimeValue,
int maxTimeValue, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::UpDownRatioDlg) , ui(new Ui::UpDownRatioDlg)
{ {
@ -43,21 +47,45 @@ UpDownRatioDlg::UpDownRatioDlg(bool useDefault, qreal initialValue,
if (useDefault) { if (useDefault) {
ui->useDefaultButton->setChecked(true); ui->useDefaultButton->setChecked(true);
} }
else if (initialValue == -1) { else if ((initialRatioValue == -1) && (initialTimeValue == -1)) {
ui->noLimitButton->setChecked(true); ui->noLimitButton->setChecked(true);
initialValue = BitTorrent::Session::instance()->globalMaxRatio(); initialRatioValue = BitTorrent::Session::instance()->globalMaxRatio();
initialTimeValue = BitTorrent::Session::instance()->globalMaxSeedingMinutes();
} }
else { else {
ui->torrentLimitButton->setChecked(true); ui->torrentLimitButton->setChecked(true);
if (initialRatioValue >= 0)
ui->checkMaxRatio->setChecked(true);
if (initialTimeValue >= 0)
ui->checkMaxTime->setChecked(true);
} }
ui->ratioSpinBox->setMinimum(0); ui->ratioSpinBox->setMinimum(0);
ui->ratioSpinBox->setMaximum(maxValue); ui->ratioSpinBox->setMaximum(maxRatioValue);
ui->ratioSpinBox->setValue(initialValue); ui->ratioSpinBox->setValue(initialRatioValue);
ui->timeSpinBox->setMinimum(0);
ui->timeSpinBox->setMaximum(maxTimeValue);
ui->timeSpinBox->setValue(initialTimeValue);
connect(ui->buttonGroup, SIGNAL(buttonClicked(int)), SLOT(handleRatioTypeChanged())); connect(ui->buttonGroup, SIGNAL(buttonClicked(int)), SLOT(handleRatioTypeChanged()));
connect(ui->checkMaxRatio, SIGNAL(toggled(bool)), this, SLOT(enableRatioSpin()));
connect(ui->checkMaxTime, SIGNAL(toggled(bool)), this, SLOT(enableTimeSpin()));
handleRatioTypeChanged(); handleRatioTypeChanged();
} }
void UpDownRatioDlg::accept()
{
if (ui->torrentLimitButton->isChecked() && !ui->checkMaxRatio->isChecked() && !ui->checkMaxTime->isChecked())
QMessageBox::critical(this, tr("No share limit method selected"),
tr("Please select a limit method first"));
else
QDialog::accept();
}
bool UpDownRatioDlg::useDefault() const bool UpDownRatioDlg::useDefault() const
{ {
return ui->useDefaultButton->isChecked(); return ui->useDefaultButton->isChecked();
@ -65,12 +93,32 @@ bool UpDownRatioDlg::useDefault() const
qreal UpDownRatioDlg::ratio() const qreal UpDownRatioDlg::ratio() const
{ {
return ui->noLimitButton->isChecked() ? -1 : ui->ratioSpinBox->value(); return (ui->noLimitButton->isChecked() || !ui->checkMaxRatio->isChecked()) ? -1 : ui->ratioSpinBox->value();
}
int UpDownRatioDlg::seedingTime() const
{
return (ui->noLimitButton->isChecked() || !ui->checkMaxTime->isChecked()) ? -1 : ui->timeSpinBox->value();
} }
void UpDownRatioDlg::handleRatioTypeChanged() void UpDownRatioDlg::handleRatioTypeChanged()
{ {
ui->ratioSpinBox->setEnabled(ui->torrentLimitButton->isChecked()); // ui->ratioSpinBox->setEnabled(ui->torrentLimitButton->isChecked());
ui->checkMaxRatio->setEnabled(ui->torrentLimitButton->isChecked());
ui->checkMaxTime->setEnabled(ui->torrentLimitButton->isChecked());
ui->ratioSpinBox->setEnabled(ui->torrentLimitButton->isChecked() && ui->checkMaxRatio->isChecked());
ui->timeSpinBox->setEnabled(ui->torrentLimitButton->isChecked() && ui->checkMaxTime->isChecked());
}
void UpDownRatioDlg::enableRatioSpin()
{
ui->ratioSpinBox->setEnabled(ui->checkMaxRatio->isChecked());
}
void UpDownRatioDlg::enableTimeSpin()
{
ui->timeSpinBox->setEnabled(ui->checkMaxTime->isChecked());
} }
UpDownRatioDlg::~UpDownRatioDlg() UpDownRatioDlg::~UpDownRatioDlg()

7
src/gui/updownratiodlg.h

@ -45,14 +45,21 @@ class UpDownRatioDlg : public QDialog
public: public:
explicit UpDownRatioDlg(bool useDefault, qreal initialValue, qreal maxValue, explicit UpDownRatioDlg(bool useDefault, qreal initialValue, qreal maxValue,
int initialTimeValue, int maxTimeValue,
QWidget *parent = 0); QWidget *parent = 0);
~UpDownRatioDlg(); ~UpDownRatioDlg();
bool useDefault() const; bool useDefault() const;
qreal ratio() const; qreal ratio() const;
int seedingTime() const;
public slots:
void accept();
private slots: private slots:
void handleRatioTypeChanged(); void handleRatioTypeChanged();
void enableRatioSpin();
void enableTimeSpin();
private: private:
Ui::UpDownRatioDlg *ui; Ui::UpDownRatioDlg *ui;

55
src/gui/updownratiodlg.ui

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>317</width> <width>399</width>
<height>152</height> <height>195</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,7 +17,7 @@
<item> <item>
<widget class="QRadioButton" name="useDefaultButton"> <widget class="QRadioButton" name="useDefaultButton">
<property name="text"> <property name="text">
<string>Use global ratio limit</string> <string>Use global share limit</string>
</property> </property>
<attribute name="buttonGroup"> <attribute name="buttonGroup">
<string>buttonGroup</string> <string>buttonGroup</string>
@ -27,7 +27,7 @@
<item> <item>
<widget class="QRadioButton" name="noLimitButton"> <widget class="QRadioButton" name="noLimitButton">
<property name="text"> <property name="text">
<string>Set no ratio limit</string> <string>Set no share limit</string>
</property> </property>
<attribute name="buttonGroup"> <attribute name="buttonGroup">
<string>buttonGroup</string> <string>buttonGroup</string>
@ -35,18 +35,18 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="0" column="0">
<widget class="QRadioButton" name="torrentLimitButton"> <widget class="QRadioButton" name="torrentLimitButton">
<property name="text"> <property name="text">
<string>Set ratio limit to</string> <string>Set share limit to</string>
</property> </property>
<attribute name="buttonGroup"> <attribute name="buttonGroup">
<string>buttonGroup</string> <string>buttonGroup</string>
</attribute> </attribute>
</widget> </widget>
</item> </item>
<item> <item row="0" column="2">
<widget class="QDoubleSpinBox" name="ratioSpinBox"> <widget class="QDoubleSpinBox" name="ratioSpinBox">
<property name="maximum"> <property name="maximum">
<double>9998.000000000000000</double> <double>9998.000000000000000</double>
@ -59,7 +59,29 @@
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="2" column="2">
<widget class="QDoubleSpinBox" name="timeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>525600.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>1440.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -72,6 +94,20 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkMaxRatio">
<property name="text">
<string>ratio</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="checkMaxTime">
<property name="text">
<string>minutes</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -135,6 +171,7 @@
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="shareButtonGroup"/>
<buttongroup name="buttonGroup"/> <buttongroup name="buttonGroup"/>
</buttongroups> </buttongroups>
</ui> </ui>

1
src/webui/extra_translations.h

@ -74,6 +74,7 @@ static const char *__TRANSLATIONS__[] = {
QT_TRANSLATE_NOOP("HttpServer", "Unknown"), QT_TRANSLATE_NOOP("HttpServer", "Unknown"),
QT_TRANSLATE_NOOP("HttpServer", "Hard Disk"), QT_TRANSLATE_NOOP("HttpServer", "Hard Disk"),
QT_TRANSLATE_NOOP("HttpServer", "Share ratio limit must be between 0 and 9998.") QT_TRANSLATE_NOOP("HttpServer", "Share ratio limit must be between 0 and 9998.")
QT_TRANSLATE_NOOP("HttpServer", "Seeding time limit must be between 0 and 525600 minutes.")
}; };
static const struct { const char *source; const char *comment; } __COMMENTED_TRANSLATIONS__[] = { static const struct { const char *source; const char *comment; } __COMMENTED_TRANSLATIONS__[] = {

6
src/webui/prefjson.cpp

@ -151,6 +151,8 @@ QByteArray prefjson::getPreferences()
// Share Ratio Limiting // Share Ratio Limiting
data["max_ratio_enabled"] = (session->globalMaxRatio() >= 0.); data["max_ratio_enabled"] = (session->globalMaxRatio() >= 0.);
data["max_ratio"] = session->globalMaxRatio(); data["max_ratio"] = session->globalMaxRatio();
data["max_seeding_time_enabled"] = (session->globalMaxSeedingMinutes() >= 0.);
data["max_seeding_time"] = session->globalMaxSeedingMinutes();
data["max_ratio_act"] = session->maxRatioAction(); data["max_ratio_act"] = session->maxRatioAction();
// Add trackers // Add trackers
data["add_trackers_enabled"] = session->isAddTrackersEnabled(); data["add_trackers_enabled"] = session->isAddTrackersEnabled();
@ -367,6 +369,10 @@ void prefjson::setPreferences(const QString& json)
session->setGlobalMaxRatio(m["max_ratio"].toReal()); session->setGlobalMaxRatio(m["max_ratio"].toReal());
else else
session->setGlobalMaxRatio(-1); session->setGlobalMaxRatio(-1);
if (m.contains("max_seeding_time_enabled"))
session->setGlobalMaxSeedingMinutes(m["max_seeding_time"].toInt());
else
session->setGlobalMaxSeedingMinutes(-1);
if (m.contains("max_ratio_act")) if (m.contains("max_ratio_act"))
session->setMaxRatioAction(static_cast<MaxRatioAction>(m["max_ratio_act"].toInt())); session->setMaxRatioAction(static_cast<MaxRatioAction>(m["max_ratio_act"].toInt()));
// Add trackers // Add trackers

59
src/webui/www/public/preferences_content.html

@ -307,14 +307,36 @@
<fieldset class="settings"> <fieldset class="settings">
<legend>QBT_TR(Share Ratio Limiting)QBT_TR[CONTEXT=OptionsDialog]</legend> <legend>QBT_TR(Share Ratio Limiting)QBT_TR[CONTEXT=OptionsDialog]</legend>
<input type="checkbox" id="max_ratio_checkbox" onClick="updateMaxRatioEnabled();"/> <table>
<tr>
<td>
<input type="checkbox" id="max_ratio_checkbox" onClick="updateMaxRatioTimeEnabled();"/>
<label for="max_ratio_checkbox">QBT_TR(Seed torrents until their ratio reaches)QBT_TR[CONTEXT=OptionsDialog]</label> <label for="max_ratio_checkbox">QBT_TR(Seed torrents until their ratio reaches)QBT_TR[CONTEXT=OptionsDialog]</label>
</td>
<td>
<input type="text" id="max_ratio_value" style="width: 4em;"/> <input type="text" id="max_ratio_value" style="width: 4em;"/>
</td>
<tr>
<td>
<input type="checkbox" id="max_seeding_time_checkbox" onClick="updateMaxRatioTimeEnabled();"/>
<label for="max_seeding_time_checkbox">QBT_TR(Seed torrents until their seeding time reaches)QBT_TR[CONTEXT=OptionsDialog]</label>
</td>
<td>
<input type="text" id="max_seeding_time_value" style="width: 4em;"/> QBT_TR(minutes)QBT_TR[CONTEXT=OptionsDialog]
</td>
</tr>
<tr>
<td style="text-align: right;">
QBT_TR(then)QBT_TR[CONTEXT=OptionsDialog] QBT_TR(then)QBT_TR[CONTEXT=OptionsDialog]
</td>
<td>
<select id="max_ratio_act"> <select id="max_ratio_act">
<option value="0">QBT_TR(Pause them)QBT_TR[CONTEXT=OptionsDialog]</option> <option value="0">QBT_TR(Pause them)QBT_TR[CONTEXT=OptionsDialog]</option>
<option value="1">QBT_TR(Remove them)QBT_TR[CONTEXT=OptionsDialog]</option> <option value="1">QBT_TR(Remove them)QBT_TR[CONTEXT=OptionsDialog]</option>
</select> </select>
</td>
</tr>
</table>
</fieldset> </fieldset>
<fieldset class="settings"> <fieldset class="settings">
@ -724,12 +746,20 @@ updateQueueingSystem = function() {
} }
} }
updateMaxRatioEnabled = function() { updateMaxRatioTimeEnabled = function() {
if($('max_ratio_checkbox').getProperty('checked')) { if($('max_ratio_checkbox').getProperty('checked')) {
$('max_ratio_value').setProperty('disabled', false); $('max_ratio_value').setProperty('disabled', false);
$('max_ratio_act').setProperty('disabled', false);
} else { } else {
$('max_ratio_value').setProperty('disabled', true); $('max_ratio_value').setProperty('disabled', true);
}
if($('max_seeding_time_checkbox').getProperty('checked')) {
$('max_seeding_time_value').setProperty('disabled', false);
} else {
$('max_seeding_time_value').setProperty('disabled', true);
}
if($('max_ratio_checkbox').getProperty('checked') || $('max_seeding_time_checkbox').getProperty('checked')) {
$('max_ratio_act').setProperty('disabled', false);
} else {
$('max_ratio_act').setProperty('disabled', true); $('max_ratio_act').setProperty('disabled', true);
} }
} }
@ -992,7 +1022,7 @@ loadPreferences = function() {
$('dont_count_slow_torrents_checkbox').setProperty('checked', pref.dont_count_slow_torrents); $('dont_count_slow_torrents_checkbox').setProperty('checked', pref.dont_count_slow_torrents);
updateQueueingSystem(); updateQueueingSystem();
// Share Ratio Limiting // Share Limiting
$('max_ratio_checkbox').setProperty('checked', pref.max_ratio_enabled); $('max_ratio_checkbox').setProperty('checked', pref.max_ratio_enabled);
if (pref.max_ratio_enabled) if (pref.max_ratio_enabled)
$('max_ratio_value').setProperty('value', pref.max_ratio); $('max_ratio_value').setProperty('value', pref.max_ratio);
@ -1000,7 +1030,14 @@ loadPreferences = function() {
$('max_ratio_value').setProperty('value', 1); $('max_ratio_value').setProperty('value', 1);
var max_ratio_act = pref.max_ratio_act.toInt(); var max_ratio_act = pref.max_ratio_act.toInt();
$('max_ratio_act').getChildren('option')[max_ratio_act].setAttribute('selected', ''); $('max_ratio_act').getChildren('option')[max_ratio_act].setAttribute('selected', '');
updateMaxRatioEnabled(); $('max_seeding_time_checkbox').setProperty('checked', pref.max_seeding_time_enabled);
if (pref.max_seeding_time_enabled)
$('max_seeding_time_value').setProperty('value', pref.max_seeding_time.toInt());
else
$('max_seeding_time_value').setProperty('value', 1440);
var max_ratio_act = pref.max_ratio_act.toInt();
$('max_ratio_act').getChildren('option')[max_ratio_act].setAttribute('selected', '');
updateMaxRatioTimeEnabled();
// Add trackers // Add trackers
$('add_trackers_checkbox').setProperty('checked', pref.add_trackers_enabled); $('add_trackers_checkbox').setProperty('checked', pref.add_trackers_enabled);
@ -1258,6 +1295,18 @@ applyPreferences = function() {
settings.set('max_ratio', max_ratio); settings.set('max_ratio', max_ratio);
settings.set('max_ratio_act', $('max_ratio_act').getProperty('value').toInt()); settings.set('max_ratio_act', $('max_ratio_act').getProperty('value').toInt());
var max_seeding_time = -1;
if($('max_seeding_time_checkbox').getProperty('checked')) {
max_seeding_time = $('max_seeding_time_value').getProperty('value').toInt();
if(isNaN(max_seeding_time) || max_seeding_time < 0 || max_seeding_time > 525600) {
alert("QBT_TR(Seeding time limit must be between 0 and 525600 minutes.)QBT_TR[CONTEXT=HttpServer]");
return;
}
}
settings.set('max_seeding_time_enabled', $('max_seeding_time_checkbox').getProperty('checked'));
settings.set('max_seeding_time', max_seeding_time);
settings.set('max_ratio_act', $('max_ratio_act').getProperty('value').toInt());
// Add trackers // Add trackers
settings.set('add_trackers_enabled', $('add_trackers_checkbox').getProperty('checked')); settings.set('add_trackers_enabled', $('add_trackers_checkbox').getProperty('checked'));
settings.set('add_trackers', $('add_trackers_textarea').getProperty('value')); settings.set('add_trackers', $('add_trackers_textarea').getProperty('value'));

Loading…
Cancel
Save