From 4e0fe5029bdbf5a977bb0b6c43698d913091b1f9 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Mon, 26 Aug 2024 13:15:19 +0500 Subject: [PATCH] UI: Options: Traffic Graph: Add "Units" option --- src/ui/conf/appgroup.cpp | 4 +- src/ui/conf/inioptions.h | 4 ++ src/ui/form/graph/axistickerspeed.cpp | 2 +- src/ui/form/graph/axistickerspeed.h | 8 +++ src/ui/form/graph/graphwindow.cpp | 17 ++++-- src/ui/form/graph/graphwindow.h | 7 +++ src/ui/form/opt/pages/applicationspage.cpp | 2 +- src/ui/form/opt/pages/graphpage.cpp | 64 ++++++++++++++++------ src/ui/form/opt/pages/graphpage.h | 6 +- src/ui/form/opt/pages/ifacepage.cpp | 9 ++- src/ui/form/opt/pages/ifacepage.h | 2 + src/ui/util/formatutil.cpp | 32 +++++++++-- src/ui/util/formatutil.h | 16 ++++-- 13 files changed, 135 insertions(+), 38 deletions(-) diff --git a/src/ui/conf/appgroup.cpp b/src/ui/conf/appgroup.cpp index 40e77a6e..cdb4d689 100644 --- a/src/ui/conf/appgroup.cpp +++ b/src/ui/conf/appgroup.cpp @@ -171,12 +171,12 @@ QString AppGroup::menuLabel() const if (enabledSpeedLimitIn() != 0) { text += QLatin1Char(' ') + QChar(0x2193) // ↓ - + FormatUtil::formatSpeed(speedLimitIn() * 1024); + + FormatUtil::formatSpeed(speedLimitIn() * 1024LL); } if (enabledSpeedLimitOut() != 0) { text += QLatin1Char(' ') + QChar(0x2191) // ↑ - + FormatUtil::formatSpeed(speedLimitOut() * 1024); + + FormatUtil::formatSpeed(speedLimitOut() * 1024LL); } if (periodEnabled()) { diff --git a/src/ui/conf/inioptions.h b/src/ui/conf/inioptions.h index 820af5fc..fac432d8 100644 --- a/src/ui/conf/inioptions.h +++ b/src/ui/conf/inioptions.h @@ -124,6 +124,10 @@ public: int graphWindowMaxSeconds() const { return valueInt("graphWindow/maxSeconds", 500); } void setGraphWindowMaxSeconds(int v) { setValue("graphWindow/maxSeconds", v); } + constexpr int graphWindowTrafUnitDefault() const { return 0; } + int graphWindowTrafUnit() const { return valueInt("graphWindow/trafUnit", 0); } + void setGraphWindowTrafUnit(int v) { setValue("graphWindow/trafUnit", v); } + constexpr QColor graphWindowColorDefault() const { return QColor(255, 255, 255); } QColor graphWindowColor() const { diff --git a/src/ui/form/graph/axistickerspeed.cpp b/src/ui/form/graph/axistickerspeed.cpp index 9831a832..80b78bef 100644 --- a/src/ui/form/graph/axistickerspeed.cpp +++ b/src/ui/form/graph/axistickerspeed.cpp @@ -17,5 +17,5 @@ QString AxisTickerSpeed::getTickLabel( Q_UNUSED(formatChar); Q_UNUSED(precision); - return FormatUtil::formatSpeed(quint32(tick)); + return FormatUtil::formatSpeed(qint64(tick), unitFormat()); } diff --git a/src/ui/form/graph/axistickerspeed.h b/src/ui/form/graph/axistickerspeed.h index 7dba3314..6de9aad9 100644 --- a/src/ui/form/graph/axistickerspeed.h +++ b/src/ui/form/graph/axistickerspeed.h @@ -3,6 +3,8 @@ #include +#include + class AxisTickerSpeed : public QCPAxisTicker { Q_GADGET @@ -10,10 +12,16 @@ class AxisTickerSpeed : public QCPAxisTicker public: explicit AxisTickerSpeed() = default; + FormatUtil::SizeFormat unitFormat() const { return m_unitFormat; } + void setUnitFormat(FormatUtil::SizeFormat v) { m_unitFormat = v; } + protected: double getTickStep(const QCPRange &range) override; QString getTickLabel( double tick, const QLocale &locale, QChar formatChar, int precision) override; + +private: + FormatUtil::SizeFormat m_unitFormat = FormatUtil::SpeedTraditionalFormat; }; #endif // AXISTICKERSPEED_H diff --git a/src/ui/form/graph/graphwindow.cpp b/src/ui/form/graph/graphwindow.cpp index fc537b51..73297a7e 100644 --- a/src/ui/form/graph/graphwindow.cpp +++ b/src/ui/form/graph/graphwindow.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -161,8 +160,8 @@ void GraphWindow::setupUi() axisRect->setMinimumMargins(QMargins(1, 2, 1, 1)); // Axis Ticker - QSharedPointer ticker(new AxisTickerSpeed()); - yAxis->setTicker(ticker); + m_ticker.reset(new AxisTickerSpeed()); + yAxis->setTicker(m_ticker); // Graph Inbound m_graphIn = new QCPBars(m_plot->xAxis, m_plot->yAxis); @@ -194,6 +193,7 @@ void GraphWindow::setupFlagsAndColors() const auto updateFlagsAndColors = [&] { updateWindowFlags(); updateColors(); + updateFormat(); }; updateFlagsAndColors(); @@ -241,6 +241,13 @@ void GraphWindow::updateColors() m_graphOut->setPen(QPen(ini()->graphWindowColorOut())); } +void GraphWindow::updateFormat() +{ + m_unitFormat = FormatUtil::graphUnitFormat(ini()->graphWindowTrafUnit()); + + m_ticker->setUnitFormat(m_unitFormat); +} + void GraphWindow::setupTimer() { connect(&m_hoverTimer, &QTimer::timeout, this, &GraphWindow::checkHoverLeave); @@ -422,8 +429,8 @@ void GraphWindow::updateWindowTitleSpeed() m_graphOut->data()->isEmpty() ? 0 : (m_graphOut->data()->constEnd() - 1)->mainValue(); setWindowTitle(QChar(0x2193) // ↓ - + FormatUtil::formatSpeed(quint32(inBits)) + ' ' + QChar(0x2191) // ↑ - + FormatUtil::formatSpeed(quint32(outBits))); + + FormatUtil::formatSpeed(quint64(inBits), m_unitFormat) + ' ' + QChar(0x2191) // ↑ + + FormatUtil::formatSpeed(quint64(outBits), m_unitFormat)); } void GraphWindow::setWindowOpacityPercent(int percent) diff --git a/src/ui/form/graph/graphwindow.h b/src/ui/form/graph/graphwindow.h index b341d641..7071cec1 100644 --- a/src/ui/form/graph/graphwindow.h +++ b/src/ui/form/graph/graphwindow.h @@ -4,6 +4,9 @@ #include #include
+#include + +class AxisTickerSpeed; class ConfManager; class FirewallConf; @@ -55,6 +58,7 @@ private: void setupFlagsAndColors(); void updateWindowFlags(); void updateColors(); + void updateFormat(); void setupTimer(); @@ -76,9 +80,12 @@ protected: private: bool m_mouseDragResize = false; + FormatUtil::SizeFormat m_unitFormat = FormatUtil::SpeedTraditionalFormat; + qint64 m_lastUnixTime = 0; GraphPlot *m_plot = nullptr; + QSharedPointer m_ticker; QCPBars *m_graphIn = nullptr; QCPBars *m_graphOut = nullptr; diff --git a/src/ui/form/opt/pages/applicationspage.cpp b/src/ui/form/opt/pages/applicationspage.cpp index 0c471d84..0e40e67b 100644 --- a/src/ui/form/opt/pages/applicationspage.cpp +++ b/src/ui/form/opt/pages/applicationspage.cpp @@ -52,7 +52,7 @@ CheckSpinCombo *createGroupLimit() QString formatSpeed(int kbits) { - return FormatUtil::formatSpeed(quint32(kbits * 1024)); + return FormatUtil::formatSpeed(kbits * 1024LL); } void pageAppGroupCheckEdited(ApplicationsPage *page, AppGroup *appGroup, bool isFlag = false) diff --git a/src/ui/form/opt/pages/graphpage.cpp b/src/ui/form/opt/pages/graphpage.cpp index 0b7632e2..74110229 100644 --- a/src/ui/form/opt/pages/graphpage.cpp +++ b/src/ui/form/opt/pages/graphpage.cpp @@ -1,6 +1,7 @@ #include "graphpage.h" #include +#include #include #include #include @@ -32,6 +33,7 @@ void GraphPage::onResetToDefault() m_graphOpacity->spinBox()->setValue(ini()->graphWindowOpacityDefault()); m_graphHoverOpacity->spinBox()->setValue(ini()->graphWindowHoverOpacityDefault()); m_graphMaxSeconds->spinBox()->setValue(ini()->graphWindowMaxSecondsDefault()); + m_comboTrafUnit->setCurrentIndex(ini()->graphWindowTrafUnitDefault()); m_graphColor->setColor(ini()->graphWindowColorDefault()); m_graphColorIn->setColor(ini()->graphWindowColorInDefault()); @@ -56,6 +58,7 @@ void GraphPage::onRetranslateUi() m_graphOpacity->label()->setText(tr("Opacity:")); m_graphHoverOpacity->label()->setText(tr("Hover opacity:")); m_graphMaxSeconds->label()->setText(tr("Max seconds:")); + m_traphUnits->setText(tr("Units:")); m_graphColor->label()->setText(tr("Background:")); m_graphColorIn->label()->setText(tr("Download:")); @@ -97,13 +100,25 @@ QLayout *GraphPage::setupColumns() QLayout *GraphPage::setupColumn1() { - auto layout = new QVBoxLayout(); - layout->setSpacing(10); - // Graph Group Box setupGraphBox(); - layout->addWidget(m_gbGraph); + auto layout = new QVBoxLayout(); + layout->setSpacing(10); + layout->addWidget(m_gbGraph); + layout->addStretch(); + + return layout; +} + +QLayout *GraphPage::setupColumn2() +{ + // Graph Colors Group Box + setupColorsBox(); + + auto layout = new QVBoxLayout(); + layout->setSpacing(10); + layout->addWidget(m_gbColors); layout->addStretch(); return layout; @@ -114,10 +129,22 @@ void GraphPage::setupGraphBox() setupGraphCheckboxes(); setupGraphOptions(); - auto layout = ControlUtil::createVLayoutByWidgets({ m_cbGraphHideOnClose, - ControlUtil::createSeparator(), m_cbGraphAlwaysOnTop, m_cbGraphFrameless, - m_cbGraphClickThrough, m_cbGraphHideOnHover, ControlUtil::createSeparator(), - m_graphOpacity, m_graphHoverOpacity, m_graphMaxSeconds }); + // Traffic Units + auto trafUnitsLayout = setupTrafUnitsLayout(); + + auto layout = new QVBoxLayout(); + layout->addWidget(m_cbGraphHideOnClose); + layout->addWidget(ControlUtil::createSeparator()); + layout->addWidget(m_cbGraphAlwaysOnTop); + layout->addWidget(m_cbGraphFrameless); + layout->addWidget(m_cbGraphClickThrough); + layout->addWidget(m_cbGraphHideOnHover); + layout->addWidget(ControlUtil::createSeparator()); + layout->addWidget(m_graphOpacity); + layout->addWidget(m_graphHoverOpacity); + layout->addWidget(m_graphMaxSeconds); + layout->addWidget(ControlUtil::createSeparator()); + layout->addLayout(trafUnitsLayout); m_gbGraph = new QGroupBox(); m_gbGraph->setLayout(layout); @@ -188,18 +215,23 @@ void GraphPage::setupGraphOptions() }); } -QLayout *GraphPage::setupColumn2() +QLayout *GraphPage::setupTrafUnitsLayout() { - auto layout = new QVBoxLayout(); - layout->setSpacing(10); + const QStringList list = { "b/s", "B/s", "ib/s", "iB/s" }; - // Graph Colors Group Box - setupColorsBox(); - layout->addWidget(m_gbColors); + m_traphUnits = ControlUtil::createLabel(); - layout->addStretch(); + m_comboTrafUnit = ControlUtil::createComboBox(list, [&](int index) { + if (ini()->graphWindowTrafUnit() != index) { + ini()->setGraphWindowTrafUnit(index); + ctrl()->setIniEdited(); + } + }); + m_comboTrafUnit->setFixedWidth(110); - return layout; + m_comboTrafUnit->setCurrentIndex(ini()->graphWindowTrafUnit()); + + return ControlUtil::createRowLayout(m_traphUnits, m_comboTrafUnit); } void GraphPage::setupColorsBox() diff --git a/src/ui/form/opt/pages/graphpage.h b/src/ui/form/opt/pages/graphpage.h index 15f9645a..394868e3 100644 --- a/src/ui/form/opt/pages/graphpage.h +++ b/src/ui/form/opt/pages/graphpage.h @@ -23,10 +23,12 @@ private: void setupUi(); QLayout *setupColumns(); QLayout *setupColumn1(); + QLayout *setupColumn2(); + void setupGraphBox(); void setupGraphCheckboxes(); void setupGraphOptions(); - QLayout *setupColumn2(); + QLayout *setupTrafUnitsLayout(); void setupColorsBox(); void setupGraphColors(); @@ -42,6 +44,8 @@ private: LabelSpin *m_graphOpacity = nullptr; LabelSpin *m_graphHoverOpacity = nullptr; LabelSpin *m_graphMaxSeconds = nullptr; + QLabel *m_traphUnits = nullptr; + QComboBox *m_comboTrafUnit = nullptr; LabelColor *m_graphColor = nullptr; LabelColor *m_graphColorIn = nullptr; diff --git a/src/ui/form/opt/pages/ifacepage.cpp b/src/ui/form/opt/pages/ifacepage.cpp index 01879075..1793c1a0 100644 --- a/src/ui/form/opt/pages/ifacepage.cpp +++ b/src/ui/form/opt/pages/ifacepage.cpp @@ -144,8 +144,7 @@ void IfacePage::retranslateComboTheme() ControlUtil::setComboBoxTexts(m_comboTheme, list); - const auto colorScheme = IniUser::colorSchemeByName(iniUser()->theme()); - m_comboTheme->setCurrentIndex(colorScheme); + updateTheme(); } void IfacePage::retranslateComboHotKey() @@ -558,3 +557,9 @@ void IfacePage::setupConfirmationsBox() m_gbConfirmations = new QGroupBox(); m_gbConfirmations->setLayout(layout); } + +void IfacePage::updateTheme() +{ + const auto colorScheme = IniUser::colorSchemeByName(iniUser()->theme()); + m_comboTheme->setCurrentIndex(colorScheme); +} diff --git a/src/ui/form/opt/pages/ifacepage.h b/src/ui/form/opt/pages/ifacepage.h index ddfa9112..5763f80d 100644 --- a/src/ui/form/opt/pages/ifacepage.h +++ b/src/ui/form/opt/pages/ifacepage.h @@ -56,6 +56,8 @@ private: QLayout *setupTrayActionLayout(); void setupConfirmationsBox(); + void updateTheme(); + private: bool m_explorerEdited : 1 = false; bool m_languageEdited : 1 = false; diff --git a/src/ui/util/formatutil.cpp b/src/ui/util/formatutil.cpp index c2569ccf..1961dc17 100644 --- a/src/ui/util/formatutil.cpp +++ b/src/ui/util/formatutil.cpp @@ -25,7 +25,7 @@ int FormatUtil::getPower(qint64 value, SizeFormat format) } if (isBase1000(format)) { - return int(qLn(qAbs(value)) / 3); + return int(std::log10(qAbs(value)) / 3); } // Compute log2(value) / 10 @@ -42,8 +42,8 @@ QString FormatUtil::formatSize(qint64 value, int power, int precision, SizeForma return QLocale().toString(value); } - const int base = isBase1000(format) ? 1000 : 1024; - const qreal powerValue = qPow(qreal(base), power); + const qreal base = isBase1000(format) ? 1000 : 1024; + const qreal powerValue = qPow(base, power); return QLocale().toString(value / powerValue, 'f', precision); } @@ -72,10 +72,32 @@ QString FormatUtil::formatDataSize(qint64 bytes, int precision, SizeFormat forma return sizeStr + ' ' + unitStr; } -QString FormatUtil::formatSpeed(quint32 bitsPerSecond) +QString FormatUtil::formatSpeed(qint64 bitsPerSecond, SizeFormat format) { - const auto format = SizeFormat(SizeTraditionalFormat | SizeBits); + if (!isBits(format)) { + bitsPerSecond /= 8; + } + const auto text = formatDataSize(bitsPerSecond, /*precision=*/0, format); return text + "/s"; } + +QStringList FormatUtil::graphUnitNames() +{ + static const QStringList list = { "b/s", "B/s", "ib/s", "iB/s" }; + + return list; +} + +FormatUtil::SizeFormat FormatUtil::graphUnitFormat(int index) +{ + static const SizeFormat list[] = { SpeedTraditionalFormat, SizeTraditionalFormat, + SpeedIecFormat, SizeIecFormat }; + + if (index < 0 || index >= std::size(list)) { + index = 0; + } + + return list[index]; +} diff --git a/src/ui/util/formatutil.h b/src/ui/util/formatutil.h index 59aaf0c7..62c62a6f 100644 --- a/src/ui/util/formatutil.h +++ b/src/ui/util/formatutil.h @@ -9,7 +9,7 @@ class FormatUtil : public QObject Q_OBJECT public: - enum SizeFormat { + enum SizeFormat : quint8 { SizeBase1000 = 0x01, // use factors of 1000 SizeBase1024 = 0x02, // use SI quantifiers @@ -18,9 +18,12 @@ public: SizeBits = 0x10, // b, Kb, Mb, Gb, ... - SizeIecFormat = (SizeBase1024 | SizeFormatIec), // base 1024, KiB, MiB, GiB, ... - SizeTraditionalFormat = (SizeBase1024 | SizeFormatSi), // base 1024, kB, MB, GB, ... - SizeSIFormat = (SizeBase1000 | SizeFormatSi) // base 1000, kB, MB, GB, ... + SizeIecFormat = (SizeBase1000 | SizeFormatIec), // base 1000, KiB, MiB, GiB, ... + SizeTraditionalFormat = (SizeBase1024 | SizeFormatSi), // base 1024, KB, MB, GB, ... + SizeSIFormat = (SizeBase1000 | SizeFormatSi), // base 1000, KB, MB, GB, ... + + SpeedTraditionalFormat = (SizeTraditionalFormat | SizeBits), // Kb/s, Mb/s, ... + SpeedIecFormat = (SizeIecFormat | SizeBits), // Kib/s, Mib/s, ... }; static int getPower(qint64 value, SizeFormat format = SizeTraditionalFormat); @@ -33,7 +36,10 @@ public: static QString formatDataSize( qint64 bytes, int precision = 2, SizeFormat format = SizeTraditionalFormat); - static QString formatSpeed(quint32 bitsPerSecond); + static QString formatSpeed(qint64 bitsPerSecond, SizeFormat format = SpeedTraditionalFormat); + + static QStringList graphUnitNames(); + static FormatUtil::SizeFormat graphUnitFormat(int index); }; #endif // FORMATUTIL_H