Show free disk space in status bar

PR #22407.
Closes #19607.
This commit is contained in:
Vladimir Golovnev 2025-03-13 14:47:10 +03:00 committed by GitHub
parent 882da47609
commit d174bc75e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 163 additions and 80 deletions

View file

@ -54,6 +54,7 @@ add_library(qbt_base STATIC
concepts/stringable.h concepts/stringable.h
digest32.h digest32.h
exceptions.h exceptions.h
freediskspacechecker.h
global.h global.h
http/connection.h http/connection.h
http/httperror.h http/httperror.h
@ -159,6 +160,7 @@ add_library(qbt_base STATIC
bittorrent/trackerentry.cpp bittorrent/trackerentry.cpp
bittorrent/trackerentrystatus.cpp bittorrent/trackerentrystatus.cpp
exceptions.cpp exceptions.cpp
freediskspacechecker.cpp
http/connection.cpp http/connection.cpp
http/httperror.cpp http/httperror.cpp
http/requestparser.cpp http/requestparser.cpp

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2025 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
@ -479,6 +479,8 @@ namespace BitTorrent
virtual QString lastExternalIPv4Address() const = 0; virtual QString lastExternalIPv4Address() const = 0;
virtual QString lastExternalIPv6Address() const = 0; virtual QString lastExternalIPv6Address() const = 0;
virtual qint64 freeDiskSpace() const = 0;
signals: signals:
void startupProgressUpdated(int progress); void startupProgressUpdated(int progress);
void addTorrentFailed(const InfoHash &infoHash, const QString &reason); void addTorrentFailed(const InfoHash &infoHash, const QString &reason);
@ -519,5 +521,6 @@ namespace BitTorrent
void trackerSuccess(Torrent *torrent, const QString &tracker); void trackerSuccess(Torrent *torrent, const QString &tracker);
void trackerWarning(Torrent *torrent, const QString &tracker); void trackerWarning(Torrent *torrent, const QString &tracker);
void trackerEntryStatusesUpdated(Torrent *torrent, const QHash<QString, TrackerEntryStatus> &updatedTrackers); void trackerEntryStatusesUpdated(Torrent *torrent, const QHash<QString, TrackerEntryStatus> &updatedTrackers);
void freeDiskSpaceChecked(qint64 result);
}; };
} }

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2025 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
@ -76,6 +76,7 @@
#include <QUuid> #include <QUuid>
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/freediskspacechecker.h"
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
@ -115,6 +116,7 @@ using namespace BitTorrent;
const Path CATEGORIES_FILE_NAME {u"categories.json"_s}; const Path CATEGORIES_FILE_NAME {u"categories.json"_s};
const int MAX_PROCESSING_RESUMEDATA_COUNT = 50; const int MAX_PROCESSING_RESUMEDATA_COUNT = 50;
const std::chrono::seconds FREEDISKSPACE_CHECK_TIMEOUT = 30s;
namespace namespace
{ {
@ -540,6 +542,8 @@ SessionImpl::SessionImpl(QObject *parent)
, m_ioThread {new QThread} , m_ioThread {new QThread}
, m_asyncWorker {new QThreadPool(this)} , m_asyncWorker {new QThreadPool(this)}
, m_recentErroredTorrentsTimer {new QTimer(this)} , m_recentErroredTorrentsTimer {new QTimer(this)}
, m_freeDiskSpaceChecker {new FreeDiskSpaceChecker(savePath())}
, m_freeDiskSpaceCheckingTimer {new QTimer(this)}
{ {
// It is required to perform async access to libtorrent sequentially // It is required to perform async access to libtorrent sequentially
m_asyncWorker->setMaxThreadCount(1); m_asyncWorker->setMaxThreadCount(1);
@ -600,6 +604,18 @@ SessionImpl::SessionImpl(QObject *parent)
, &Net::ProxyConfigurationManager::proxyConfigurationChanged , &Net::ProxyConfigurationManager::proxyConfigurationChanged
, this, &SessionImpl::configureDeferred); , this, &SessionImpl::configureDeferred);
m_freeDiskSpaceChecker->moveToThread(m_ioThread.get());
connect(m_ioThread.get(), &QThread::finished, m_freeDiskSpaceChecker, &QObject::deleteLater);
m_freeDiskSpaceCheckingTimer->setInterval(FREEDISKSPACE_CHECK_TIMEOUT);
m_freeDiskSpaceCheckingTimer->setSingleShot(true);
connect(m_freeDiskSpaceCheckingTimer, &QTimer::timeout, m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::check);
connect(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, this, [this](const qint64 value)
{
m_freeDiskSpace = value;
m_freeDiskSpaceCheckingTimer->start();
emit freeDiskSpaceChecked(m_freeDiskSpace);
});
m_fileSearcher = new FileSearcher; m_fileSearcher = new FileSearcher;
m_fileSearcher->moveToThread(m_ioThread.get()); m_fileSearcher->moveToThread(m_ioThread.get());
connect(m_ioThread.get(), &QThread::finished, m_fileSearcher, &QObject::deleteLater); connect(m_ioThread.get(), &QThread::finished, m_fileSearcher, &QObject::deleteLater);
@ -613,6 +629,8 @@ SessionImpl::SessionImpl(QObject *parent)
m_ioThread->setObjectName("SessionImpl m_ioThread"); m_ioThread->setObjectName("SessionImpl m_ioThread");
m_ioThread->start(); m_ioThread->start();
QMetaObject::invokeMethod(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::check);
initMetrics(); initMetrics();
loadStatistics(); loadStatistics();
@ -3266,6 +3284,14 @@ void SessionImpl::setSavePath(const Path &path)
m_savePath = newPath; m_savePath = newPath;
for (TorrentImpl *const torrent : asConst(m_torrents)) for (TorrentImpl *const torrent : asConst(m_torrents))
torrent->handleCategoryOptionsChanged(); torrent->handleCategoryOptionsChanged();
m_freeDiskSpace = -1;
m_freeDiskSpaceCheckingTimer->stop();
QMetaObject::invokeMethod(m_freeDiskSpaceChecker, [checker = m_freeDiskSpaceChecker, pathToCheck = m_savePath]
{
checker->setPathToCheck(pathToCheck);
checker->check();
});
} }
void SessionImpl::setDownloadPath(const Path &path) void SessionImpl::setDownloadPath(const Path &path)
@ -5113,6 +5139,11 @@ QString SessionImpl::lastExternalIPv6Address() const
return m_lastExternalIPv6Address; return m_lastExternalIPv6Address;
} }
qint64 SessionImpl::freeDiskSpace() const
{
return m_freeDiskSpace;
}
bool SessionImpl::isListening() const bool SessionImpl::isListening() const
{ {
return m_nativeSessionExtension->isSessionListening(); return m_nativeSessionExtension->isSessionListening();

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2025 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
@ -64,6 +64,7 @@ class QUrl;
class BandwidthScheduler; class BandwidthScheduler;
class FileSearcher; class FileSearcher;
class FilterParserThread; class FilterParserThread;
class FreeDiskSpaceChecker;
class NativeSessionExtension; class NativeSessionExtension;
namespace BitTorrent namespace BitTorrent
@ -448,6 +449,8 @@ namespace BitTorrent
QString lastExternalIPv4Address() const override; QString lastExternalIPv4Address() const override;
QString lastExternalIPv6Address() const override; QString lastExternalIPv6Address() const override;
qint64 freeDiskSpace() const override;
// Torrent interface // Torrent interface
void handleTorrentResumeDataRequested(const TorrentImpl *torrent); void handleTorrentResumeDataRequested(const TorrentImpl *torrent);
void handleTorrentShareLimitChanged(TorrentImpl *torrent); void handleTorrentShareLimitChanged(TorrentImpl *torrent);
@ -850,6 +853,10 @@ namespace BitTorrent
QList<TorrentImpl *> m_pendingFinishedTorrents; QList<TorrentImpl *> m_pendingFinishedTorrents;
FreeDiskSpaceChecker *m_freeDiskSpaceChecker = nullptr;
QTimer *m_freeDiskSpaceCheckingTimer = nullptr;
qint64 m_freeDiskSpace = -1;
friend void Session::initInstance(); friend void Session::initInstance();
friend void Session::freeInstance(); friend void Session::freeInstance();
friend Session *Session::instance(); friend Session *Session::instance();

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2023-2025 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com> * Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -29,16 +29,24 @@
#include "freediskspacechecker.h" #include "freediskspacechecker.h"
#include "base/bittorrent/session.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
qint64 FreeDiskSpaceChecker::lastResult() const FreeDiskSpaceChecker::FreeDiskSpaceChecker(const Path &pathToCheck)
: m_pathToCheck {pathToCheck}
{ {
return m_lastResult; }
Path FreeDiskSpaceChecker::pathToCheck() const
{
return m_pathToCheck;
}
void FreeDiskSpaceChecker::setPathToCheck(const Path &newPathToCheck)
{
m_pathToCheck = newPathToCheck;
} }
void FreeDiskSpaceChecker::check() void FreeDiskSpaceChecker::check()
{ {
m_lastResult = Utils::Fs::freeDiskSpaceOnPath(BitTorrent::Session::instance()->savePath()); emit checked(Utils::Fs::freeDiskSpaceOnPath(m_pathToCheck));
emit checked(m_lastResult);
} }

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2023-2025 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com> * Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -31,15 +31,18 @@
#include <QObject> #include <QObject>
#include "base/path.h"
class FreeDiskSpaceChecker final : public QObject class FreeDiskSpaceChecker final : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY_MOVE(FreeDiskSpaceChecker) Q_DISABLE_COPY_MOVE(FreeDiskSpaceChecker)
public: public:
using QObject::QObject; FreeDiskSpaceChecker(const Path &pathToCheck);
qint64 lastResult() const; Path pathToCheck() const;
void setPathToCheck(const Path &newPathToCheck);
public slots: public slots:
void check(); void check();
@ -48,5 +51,5 @@ signals:
void checked(qint64 freeSpaceSize); void checked(qint64 freeSpaceSize);
private: private:
qint64 m_lastResult = 0; Path m_pathToCheck;
}; };

View file

@ -359,6 +359,19 @@ void Preferences::setStatusbarDisplayed(const bool displayed)
setValue(u"Preferences/General/StatusbarDisplayed"_s, displayed); setValue(u"Preferences/General/StatusbarDisplayed"_s, displayed);
} }
bool Preferences::isStatusbarFreeDiskSpaceDisplayed() const
{
return value(u"Preferences/General/StatusbarFreeDiskSpaceDisplayed"_s, false);
}
void Preferences::setStatusbarFreeDiskSpaceDisplayed(const bool displayed)
{
if (displayed == isStatusbarFreeDiskSpaceDisplayed())
return;
setValue(u"Preferences/General/StatusbarFreeDiskSpaceDisplayed"_s, displayed);
}
bool Preferences::isStatusbarExternalIPDisplayed() const bool Preferences::isStatusbarExternalIPDisplayed() const
{ {
return value(u"Preferences/General/StatusbarExternalIPDisplayed"_s, false); return value(u"Preferences/General/StatusbarExternalIPDisplayed"_s, false);

View file

@ -119,6 +119,8 @@ public:
void setHideZeroComboValues(int n); void setHideZeroComboValues(int n);
bool isStatusbarDisplayed() const; bool isStatusbarDisplayed() const;
void setStatusbarDisplayed(bool displayed); void setStatusbarDisplayed(bool displayed);
bool isStatusbarFreeDiskSpaceDisplayed() const;
void setStatusbarFreeDiskSpaceDisplayed(bool displayed);
bool isStatusbarExternalIPDisplayed() const; bool isStatusbarExternalIPDisplayed() const;
void setStatusbarExternalIPDisplayed(bool displayed); void setStatusbarExternalIPDisplayed(bool displayed);
bool isToolbarDisplayed() const; bool isToolbarDisplayed() const;

View file

@ -355,6 +355,7 @@ void OptionsDialog::loadBehaviorTabOptions()
// Groupbox's check state must be initialized after some of its children if they are manually enabled/disabled // Groupbox's check state must be initialized after some of its children if they are manually enabled/disabled
m_ui->checkFileLog->setChecked(app()->isFileLoggerEnabled()); m_ui->checkFileLog->setChecked(app()->isFileLoggerEnabled());
m_ui->checkBoxFreeDiskSpaceStatusBar->setChecked(pref->isStatusbarFreeDiskSpaceDisplayed());
m_ui->checkBoxExternalIPStatusBar->setChecked(pref->isStatusbarExternalIPDisplayed()); m_ui->checkBoxExternalIPStatusBar->setChecked(pref->isStatusbarExternalIPDisplayed());
m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled()); m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled());
@ -443,6 +444,7 @@ void OptionsDialog::loadBehaviorTabOptions()
connect(m_ui->spinFileLogAge, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); connect(m_ui->spinFileLogAge, qSpinBoxValueChanged, this, &ThisType::enableApplyButton);
connect(m_ui->comboFileLogAgeType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboFileLogAgeType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
connect(m_ui->checkBoxFreeDiskSpaceStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkBoxExternalIPStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkBoxExternalIPStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->checkBoxPerformanceWarning, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkBoxPerformanceWarning, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
} }
@ -536,6 +538,7 @@ void OptionsDialog::saveBehaviorTabOptions() const
app()->setStartUpWindowState(m_ui->windowStateComboBox->currentData().value<WindowState>()); app()->setStartUpWindowState(m_ui->windowStateComboBox->currentData().value<WindowState>());
pref->setStatusbarFreeDiskSpaceDisplayed(m_ui->checkBoxFreeDiskSpaceStatusBar->isChecked());
pref->setStatusbarExternalIPDisplayed(m_ui->checkBoxExternalIPStatusBar->isChecked()); pref->setStatusbarExternalIPDisplayed(m_ui->checkBoxExternalIPStatusBar->isChecked());
session->setPerformanceWarningEnabled(m_ui->checkBoxPerformanceWarning->isChecked()); session->setPerformanceWarningEnabled(m_ui->checkBoxPerformanceWarning->isChecked());
} }

View file

@ -819,6 +819,13 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxFreeDiskSpaceStatusBar">
<property name="text">
<string>Show free disk space in status bar</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="checkBoxExternalIPStatusBar"> <widget class="QCheckBox" name="checkBoxExternalIPStatusBar">
<property name="text"> <property name="text">

View file

@ -44,6 +44,19 @@
#include "uithememanager.h" #include "uithememanager.h"
#include "utils.h" #include "utils.h"
namespace
{
QWidget *createSeparator(QWidget *parent)
{
QFrame *separator = new QFrame(parent);
separator->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MACOS
separator->setFrameShadow(QFrame::Raised);
#endif
return separator;
}
}
StatusBar::StatusBar(QWidget *parent) StatusBar::StatusBar(QWidget *parent)
: QStatusBar(parent) : QStatusBar(parent)
{ {
@ -87,11 +100,17 @@ StatusBar::StatusBar(QWidget *parent)
m_upSpeedLbl->setStyleSheet(u"text-align:left;"_s); m_upSpeedLbl->setStyleSheet(u"text-align:left;"_s);
m_upSpeedLbl->setMinimumWidth(200); m_upSpeedLbl->setMinimumWidth(200);
m_freeDiskSpaceLbl = new QLabel(tr("Free space: N/A"));
m_freeDiskSpaceLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
m_freeDiskSpaceSeparator = createSeparator(m_freeDiskSpaceLbl);
m_lastExternalIPsLbl = new QLabel(tr("External IP: N/A")); m_lastExternalIPsLbl = new QLabel(tr("External IP: N/A"));
m_lastExternalIPsLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); m_lastExternalIPsLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
m_lastExternalIPsSeparator = createSeparator(m_lastExternalIPsLbl);
m_DHTLbl = new QLabel(tr("DHT: %1 nodes").arg(0), this); m_DHTLbl = new QLabel(tr("DHT: %1 nodes").arg(0), this);
m_DHTLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); m_DHTLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
m_DHTSeparator = createSeparator(m_DHTLbl);
m_altSpeedsBtn = new QPushButton(this); m_altSpeedsBtn = new QPushButton(this);
m_altSpeedsBtn->setFlat(true); m_altSpeedsBtn->setFlat(true);
@ -113,52 +132,42 @@ StatusBar::StatusBar(QWidget *parent)
m_connecStatusLblIcon->setMaximumWidth(Utils::Gui::largeIconSize().width()); m_connecStatusLblIcon->setMaximumWidth(Utils::Gui::largeIconSize().width());
m_altSpeedsBtn->setMaximumWidth(Utils::Gui::largeIconSize().width()); m_altSpeedsBtn->setMaximumWidth(Utils::Gui::largeIconSize().width());
QFrame *statusSep1 = new QFrame(this); layout->addWidget(m_freeDiskSpaceLbl);
statusSep1->setFrameStyle(QFrame::VLine); layout->addWidget(m_freeDiskSpaceSeparator);
#ifndef Q_OS_MACOS
statusSep1->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep2 = new QFrame(this);
statusSep2->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MACOS
statusSep2->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep3 = new QFrame(this);
statusSep3->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MACOS
statusSep3->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep4 = new QFrame(this);
statusSep4->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MACOS
statusSep4->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep5 = new QFrame(this);
statusSep5->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MACOS
statusSep5->setFrameShadow(QFrame::Raised);
#endif
layout->addWidget(m_lastExternalIPsLbl); layout->addWidget(m_lastExternalIPsLbl);
layout->addWidget(statusSep1); layout->addWidget(m_lastExternalIPsSeparator);
layout->addWidget(m_DHTLbl); layout->addWidget(m_DHTLbl);
layout->addWidget(statusSep2); layout->addWidget(m_DHTSeparator);
layout->addWidget(m_connecStatusLblIcon); layout->addWidget(m_connecStatusLblIcon);
layout->addWidget(statusSep3); layout->addWidget(createSeparator(m_connecStatusLblIcon));
layout->addWidget(m_altSpeedsBtn); layout->addWidget(m_altSpeedsBtn);
layout->addWidget(statusSep4); layout->addWidget(createSeparator(m_altSpeedsBtn));
layout->addWidget(m_dlSpeedLbl); layout->addWidget(m_dlSpeedLbl);
layout->addWidget(statusSep5); layout->addWidget(createSeparator(m_dlSpeedLbl));
layout->addWidget(m_upSpeedLbl); layout->addWidget(m_upSpeedLbl);
addPermanentWidget(container); addPermanentWidget(container);
setStyleSheet(u"QWidget {margin: 0;}"_s); setStyleSheet(u"QWidget {margin: 0;}"_s);
container->adjustSize(); container->adjustSize();
adjustSize(); adjustSize();
updateFreeDiskSpaceVisibility();
updateExternalAddressesVisibility(); updateExternalAddressesVisibility();
// Is DHT enabled // Is DHT enabled
m_DHTLbl->setVisible(session->isDHTEnabled()); const bool isDHTVisible = session->isDHTEnabled();
m_DHTLbl->setVisible(isDHTVisible);
m_DHTSeparator->setVisible(isDHTVisible);
refresh(); refresh();
connect(session, &BitTorrent::Session::statsUpdated, this, &StatusBar::refresh); connect(session, &BitTorrent::Session::statsUpdated, this, &StatusBar::refresh);
updateFreeDiskSpaceLabel(session->freeDiskSpace());
connect(session, &BitTorrent::Session::freeDiskSpaceChecked, this, &StatusBar::updateFreeDiskSpaceLabel);
connect(Preferences::instance(), &Preferences::changed, this, &StatusBar::optionsSaved); connect(Preferences::instance(), &Preferences::changed, this, &StatusBar::optionsSaved);
} }
@ -216,15 +225,28 @@ void StatusBar::updateDHTNodesNumber()
if (BitTorrent::Session::instance()->isDHTEnabled()) if (BitTorrent::Session::instance()->isDHTEnabled())
{ {
m_DHTLbl->setVisible(true); m_DHTLbl->setVisible(true);
m_DHTLbl->setText(tr("DHT: %1 nodes") m_DHTSeparator->setVisible(true);
.arg(BitTorrent::Session::instance()->status().dhtNodes)); m_DHTLbl->setText(tr("DHT: %1 nodes").arg(BitTorrent::Session::instance()->status().dhtNodes));
} }
else else
{ {
m_DHTLbl->setVisible(false); m_DHTLbl->setVisible(false);
m_DHTSeparator->setVisible(false);
} }
} }
void StatusBar::updateFreeDiskSpaceLabel(const qint64 value)
{
m_freeDiskSpaceLbl->setText(tr("Free space: ") + Utils::Misc::friendlyUnit(value));
}
void StatusBar::updateFreeDiskSpaceVisibility()
{
const bool isVisible = Preferences::instance()->isStatusbarFreeDiskSpaceDisplayed();
m_freeDiskSpaceLbl->setVisible(isVisible);
m_freeDiskSpaceSeparator->setVisible(isVisible);
}
void StatusBar::updateExternalAddressesLabel() void StatusBar::updateExternalAddressesLabel()
{ {
const QString lastExternalIPv4Address = BitTorrent::Session::instance()->lastExternalIPv4Address(); const QString lastExternalIPv4Address = BitTorrent::Session::instance()->lastExternalIPv4Address();
@ -244,7 +266,9 @@ void StatusBar::updateExternalAddressesLabel()
void StatusBar::updateExternalAddressesVisibility() void StatusBar::updateExternalAddressesVisibility()
{ {
m_lastExternalIPsLbl->setVisible(Preferences::instance()->isStatusbarExternalIPDisplayed()); const bool isVisible = Preferences::instance()->isStatusbarExternalIPDisplayed();
m_lastExternalIPsLbl->setVisible(isVisible);
m_lastExternalIPsSeparator->setVisible(isVisible);
} }
void StatusBar::updateSpeedLabels() void StatusBar::updateSpeedLabels()
@ -300,5 +324,6 @@ void StatusBar::capSpeed()
void StatusBar::optionsSaved() void StatusBar::optionsSaved()
{ {
updateFreeDiskSpaceVisibility();
updateExternalAddressesVisibility(); updateExternalAddressesVisibility();
} }

View file

@ -63,14 +63,20 @@ private slots:
private: private:
void updateConnectionStatus(); void updateConnectionStatus();
void updateDHTNodesNumber(); void updateDHTNodesNumber();
void updateFreeDiskSpaceLabel(qint64 value);
void updateFreeDiskSpaceVisibility();
void updateExternalAddressesLabel(); void updateExternalAddressesLabel();
void updateExternalAddressesVisibility(); void updateExternalAddressesVisibility();
void updateSpeedLabels(); void updateSpeedLabels();
QPushButton *m_dlSpeedLbl = nullptr; QPushButton *m_dlSpeedLbl = nullptr;
QPushButton *m_upSpeedLbl = nullptr; QPushButton *m_upSpeedLbl = nullptr;
QLabel *m_freeDiskSpaceLbl = nullptr;
QWidget *m_freeDiskSpaceSeparator = nullptr;
QLabel *m_lastExternalIPsLbl = nullptr; QLabel *m_lastExternalIPsLbl = nullptr;
QWidget *m_lastExternalIPsSeparator = nullptr;
QLabel *m_DHTLbl = nullptr; QLabel *m_DHTLbl = nullptr;
QWidget *m_DHTSeparator = nullptr;
QPushButton *m_connecStatusLblIcon = nullptr; QPushButton *m_connecStatusLblIcon = nullptr;
QPushButton *m_altSpeedsBtn = nullptr; QPushButton *m_altSpeedsBtn = nullptr;
}; };

View file

@ -13,7 +13,6 @@ add_library(qbt_webui STATIC
api/torrentscontroller.h api/torrentscontroller.h
api/transfercontroller.h api/transfercontroller.h
api/serialize/serialize_torrent.h api/serialize/serialize_torrent.h
freediskspacechecker.h
webapplication.h webapplication.h
webui.h webui.h
@ -30,7 +29,6 @@ add_library(qbt_webui STATIC
api/torrentscontroller.cpp api/torrentscontroller.cpp
api/transfercontroller.cpp api/transfercontroller.cpp
api/serialize/serialize_torrent.cpp api/serialize/serialize_torrent.cpp
freediskspacechecker.cpp
webapplication.cpp webapplication.cpp
webui.cpp webui.cpp
) )

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014-2024 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2014-2025 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch> * Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -43,10 +43,10 @@
#include <QNetworkCookie> #include <QNetworkCookie>
#include <QRegularExpression> #include <QRegularExpression>
#include <QThread> #include <QThread>
#include <QTimer>
#include <QUrl> #include <QUrl>
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrentcreationmanager.h" #include "base/bittorrent/torrentcreationmanager.h"
#include "base/http/httperror.h" #include "base/http/httperror.h"
#include "base/logger.h" #include "base/logger.h"
@ -67,7 +67,6 @@
#include "api/torrentcreatorcontroller.h" #include "api/torrentcreatorcontroller.h"
#include "api/torrentscontroller.h" #include "api/torrentscontroller.h"
#include "api/transfercontroller.h" #include "api/transfercontroller.h"
#include "freediskspacechecker.h"
const int MAX_ALLOWED_FILESIZE = 10 * 1024 * 1024; const int MAX_ALLOWED_FILESIZE = 10 * 1024 * 1024;
const QString DEFAULT_SESSION_COOKIE_NAME = u"SID"_s; const QString DEFAULT_SESSION_COOKIE_NAME = u"SID"_s;
@ -76,10 +75,6 @@ const QString WWW_FOLDER = u":/www"_s;
const QString PUBLIC_FOLDER = u"/public"_s; const QString PUBLIC_FOLDER = u"/public"_s;
const QString PRIVATE_FOLDER = u"/private"_s; const QString PRIVATE_FOLDER = u"/private"_s;
using namespace std::chrono_literals;
const std::chrono::seconds FREEDISKSPACE_CHECK_TIMEOUT = 30s;
namespace namespace
{ {
QStringMap parseCookie(const QStringView cookieStr) QStringMap parseCookie(const QStringView cookieStr)
@ -161,9 +156,6 @@ WebApplication::WebApplication(IApplication *app, QObject *parent)
: ApplicationComponent(app, parent) : ApplicationComponent(app, parent)
, m_cacheID {QString::number(Utils::Random::rand(), 36)} , m_cacheID {QString::number(Utils::Random::rand(), 36)}
, m_authController {new AuthController(this, app, this)} , m_authController {new AuthController(this, app, this)}
, m_workerThread {new QThread}
, m_freeDiskSpaceChecker {new FreeDiskSpaceChecker}
, m_freeDiskSpaceCheckingTimer {new QTimer(this)}
, m_torrentCreationManager {new BitTorrent::TorrentCreationManager(app, this)} , m_torrentCreationManager {new BitTorrent::TorrentCreationManager(app, this)}
{ {
declarePublicAPI(u"auth/login"_s); declarePublicAPI(u"auth/login"_s);
@ -181,17 +173,6 @@ WebApplication::WebApplication(IApplication *app, QObject *parent)
} }
m_sessionCookieName = DEFAULT_SESSION_COOKIE_NAME; m_sessionCookieName = DEFAULT_SESSION_COOKIE_NAME;
} }
m_freeDiskSpaceChecker->moveToThread(m_workerThread.get());
connect(m_workerThread.get(), &QThread::finished, m_freeDiskSpaceChecker, &QObject::deleteLater);
m_workerThread->setObjectName("WebApplication m_workerThread");
m_workerThread->start();
m_freeDiskSpaceCheckingTimer->setInterval(FREEDISKSPACE_CHECK_TIMEOUT);
m_freeDiskSpaceCheckingTimer->setSingleShot(true);
connect(m_freeDiskSpaceCheckingTimer, &QTimer::timeout, m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::check);
connect(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, m_freeDiskSpaceCheckingTimer, qOverload<>(&QTimer::start));
QMetaObject::invokeMethod(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::check);
} }
WebApplication::~WebApplication() WebApplication::~WebApplication()
@ -739,9 +720,10 @@ void WebApplication::sessionStart()
m_currentSession->registerAPIController(u"torrents"_s, new TorrentsController(app(), m_currentSession)); m_currentSession->registerAPIController(u"torrents"_s, new TorrentsController(app(), m_currentSession));
m_currentSession->registerAPIController(u"transfer"_s, new TransferController(app(), m_currentSession)); m_currentSession->registerAPIController(u"transfer"_s, new TransferController(app(), m_currentSession));
const auto *btSession = BitTorrent::Session::instance();
auto *syncController = new SyncController(app(), m_currentSession); auto *syncController = new SyncController(app(), m_currentSession);
syncController->updateFreeDiskSpace(m_freeDiskSpaceChecker->lastResult()); syncController->updateFreeDiskSpace(btSession->freeDiskSpace());
connect(m_freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, syncController, &SyncController::updateFreeDiskSpace); connect(btSession, &BitTorrent::Session::freeDiskSpaceChecked, syncController, &SyncController::updateFreeDiskSpace);
m_currentSession->registerAPIController(u"sync"_s, syncController); m_currentSession->registerAPIController(u"sync"_s, syncController);
QNetworkCookie cookie {m_sessionCookieName.toLatin1(), m_currentSession->id().toLatin1()}; QNetworkCookie cookie {m_sessionCookieName.toLatin1(), m_currentSession->id().toLatin1()};

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014-2024 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2014-2025 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch> * Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -50,17 +50,13 @@
#include "base/http/types.h" #include "base/http/types.h"
#include "base/path.h" #include "base/path.h"
#include "base/utils/net.h" #include "base/utils/net.h"
#include "base/utils/thread.h"
#include "base/utils/version.h" #include "base/utils/version.h"
#include "api/isessionmanager.h" #include "api/isessionmanager.h"
inline const Utils::Version<3, 2> API_VERSION {2, 11, 4}; inline const Utils::Version<3, 2> API_VERSION {2, 11, 4};
class QTimer;
class APIController; class APIController;
class AuthController; class AuthController;
class FreeDiskSpaceChecker;
class WebApplication; class WebApplication;
namespace BitTorrent namespace BitTorrent
@ -259,8 +255,5 @@ private:
QList<Http::Header> m_prebuiltHeaders; QList<Http::Header> m_prebuiltHeaders;
Utils::Thread::UniquePtr m_workerThread;
FreeDiskSpaceChecker *m_freeDiskSpaceChecker = nullptr;
QTimer *m_freeDiskSpaceCheckingTimer = nullptr;
BitTorrent::TorrentCreationManager *m_torrentCreationManager = nullptr; BitTorrent::TorrentCreationManager *m_torrentCreationManager = nullptr;
}; };