mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-05 13:28:03 +03:00
Combine traffic metrics into one card
Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Vendored
+12
-36
@@ -3072,30 +3072,6 @@ TRANSLATION = {
|
||||
"ZH": "正在检测...",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Connect to a proxy to view endpoint information.": {
|
||||
"source": [
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
],
|
||||
"RU": "Подключитесь к прокси, чтобы просмотреть информацию о выходном узле.",
|
||||
"ZH": "连接代理后可查看出口信息。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Connecting...": {
|
||||
"source": [
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
],
|
||||
"RU": "Подключение...",
|
||||
"ZH": "正在连接...",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Proxy endpoint information is unavailable.": {
|
||||
"source": [
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
],
|
||||
"RU": "Информация о выходном узле прокси недоступна.",
|
||||
"ZH": "代理出口信息不可用。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Approximate location unavailable": {
|
||||
"source": [
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
@@ -3141,7 +3117,7 @@ TRANSLATION = {
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
],
|
||||
"RU": "Местоположение приблизительно определено по публичному IP и может быть неточным.",
|
||||
"ZH": "位置信息根据公网 IP 估算,可能不准确。",
|
||||
"ZH": "位置信息根据公网IP估算,可能不准确。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Not available": {
|
||||
@@ -3160,14 +3136,6 @@ TRANSLATION = {
|
||||
"ZH": "未知",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Endpoint inspection is disabled.": {
|
||||
"source": [
|
||||
"Furious.Widget.EndpointInfoWidget"
|
||||
],
|
||||
"RU": "Проверка конечной точки отключена.",
|
||||
"ZH": "代理端点检测已禁用。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Enable Proxy Endpoint Information": {
|
||||
"source": [
|
||||
"Furious.Window.SettingsPage"
|
||||
@@ -3213,7 +3181,7 @@ TRANSLATION = {
|
||||
"Furious.Window.SettingsPage"
|
||||
],
|
||||
"RU": "<b>Публичный IP-адрес</b><br>\nПубличные IPv4- и IPv6-адреса прокси проверяются<br>\nчерез активное прокси-соединение с помощью Cloudflare,<br>\nа ipify используется как резервный сервис.<br>\nЭти сервисы могут видеть публичный IP-адрес прокси.",
|
||||
"ZH": "<b>公网 IP</b><br>\n系统通过当前代理连接<br>\n使用 Cloudflare 检查代理的公网 IPv4 和 IPv6 地址,<br>\n并以 ipify 作为备用服务。<br>\n这些服务可以看到代理的公网 IP。",
|
||||
"ZH": "<b>公网 IP</b><br>\n系统通过当前代理连接<br>\n使用Cloudflare检查代理的公网IPv4和IPv6地址,<br>\n并以ipify作为备用服务。<br>\n这些服务可以看到代理的公网IP。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"<b>Approximate Location</b><br>\nThe detected public IP is sent to ipapi.co<br>\nto estimate country, city, region, and network organization.<br>\nIP-based location can be inaccurate.": {
|
||||
@@ -3221,7 +3189,7 @@ TRANSLATION = {
|
||||
"Furious.Window.SettingsPage"
|
||||
],
|
||||
"RU": "<b>Приблизительное местоположение</b><br>\nОбнаруженный публичный IP-адрес отправляется в ipapi.co<br>\nдля определения страны, города, региона и сетевой организации.<br>\nГеолокация по IP может быть неточной.",
|
||||
"ZH": "<b>大致位置</b><br>\n系统将检测到的公网 IP 发送至 ipapi.co,<br>\n用于估算国家、城市、地区和网络运营组织。<br>\n基于 IP 的位置可能不准确。",
|
||||
"ZH": "<b>大致位置</b><br>\n系统将检测到的公网IP发送至ipapi.co,<br>\n用于估算国家、城市、地区和网络运营组织。<br>\n基于IP的位置可能不准确。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"<b>Map</b><br>\nMap styles and tiles for the approximate area are loaded<br>\nfrom OpenFreeMap, using OpenStreetMap data.<br>\nOpenFreeMap receives these map requests.": {
|
||||
@@ -3229,7 +3197,15 @@ TRANSLATION = {
|
||||
"Furious.Window.SettingsPage"
|
||||
],
|
||||
"RU": "<b>Карта</b><br>\nСтили и тайлы карты приблизительной области<br>\nзагружаются из OpenFreeMap с использованием данных OpenStreetMap.<br>\nOpenFreeMap получает эти запросы карты.",
|
||||
"ZH": "<b>地图</b><br>\n大致区域的地图样式和图块从 OpenFreeMap 加载,<br>\n并使用 OpenStreetMap 数据。<br>\nOpenFreeMap 会接收这些地图请求。",
|
||||
"ZH": "<b>地图</b><br>\n大致区域的地图样式和图块从OpenFreeMap加载,<br>\n并使用OpenStreetMap数据。<br>\nOpenFreeMap会接收这些地图请求。",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Traffic Statistics": {
|
||||
"source": [
|
||||
"Furious.Window.MetricsPage"
|
||||
],
|
||||
"RU": "Статистика трафика",
|
||||
"ZH": "流量统计",
|
||||
"isReviewed": "True"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,13 +262,16 @@ def baseStyleSheet(palette):
|
||||
image: none;
|
||||
}}
|
||||
|
||||
QFrame#MetricsSection {{
|
||||
QFrame#MetricsSection,
|
||||
QFrame#TrafficMetricsCard {{
|
||||
border: 1px solid {palette['border']};
|
||||
border-radius: 10px;
|
||||
background-color: {palette['panel']};
|
||||
}}
|
||||
|
||||
QLabel#MetricsSectionTitle {{
|
||||
QLabel#MetricsSectionTitle,
|
||||
QLabel#TrafficMetricsCardTitle,
|
||||
QLabel#MetricsDirectionTitle {{
|
||||
color: {palette['text_strong']};
|
||||
font-size: 12pt;
|
||||
font-weight: 600;
|
||||
|
||||
+121
-74
@@ -70,38 +70,104 @@ class _MetricCard(QFrame):
|
||||
self.graph.setMetricLabel(title)
|
||||
|
||||
|
||||
class _MetricsSection(QFrame):
|
||||
"""Group speed and traffic-usage graphs for one direction."""
|
||||
class _TrafficMetricsCard(QFrame):
|
||||
"""Group selectors and all traffic graphs in one metrics card."""
|
||||
|
||||
def __init__(self, speedGraph, usageGraph, parent=None):
|
||||
"""Initialize a two-card metrics section."""
|
||||
def __init__(
|
||||
self,
|
||||
downloadSpeedGraph,
|
||||
downloadUsageGraph,
|
||||
uploadSpeedGraph,
|
||||
uploadUsageGraph,
|
||||
parent=None,
|
||||
):
|
||||
"""Initialize the combined download and upload metrics card."""
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName('MetricsSection')
|
||||
self.setObjectName('TrafficMetricsCard')
|
||||
|
||||
self.titleLabel = AppQLabel(translatable=False, parent=self)
|
||||
self.titleLabel.setObjectName('MetricsSectionTitle')
|
||||
self.titleLabel = AppQLabel(_('Traffic Statistics'), parent=self)
|
||||
self.titleLabel.setObjectName('TrafficMetricsCardTitle')
|
||||
|
||||
self.speedCard = _MetricCard(speedGraph, parent=self)
|
||||
self.usageCard = _MetricCard(usageGraph, parent=self)
|
||||
self.timeRangeLabel, self.granularityLabel = (
|
||||
AppQLabel(_('Time Range'), parent=self),
|
||||
AppQLabel(_('Granularity'), parent=self),
|
||||
)
|
||||
|
||||
graphLayout = QHBoxLayout()
|
||||
graphLayout.setContentsMargins(0, 0, 0, 0)
|
||||
graphLayout.setSpacing(12)
|
||||
graphLayout.addWidget(self.speedCard, 1)
|
||||
graphLayout.addWidget(self.usageCard, 1)
|
||||
self.timeRangeComboBox, self.granularityComboBox = (
|
||||
AppQComboBox(parent=self),
|
||||
AppQComboBox(parent=self),
|
||||
)
|
||||
|
||||
self.timeRangeComboBox.setMinimumWidth(160)
|
||||
self.granularityComboBox.setMinimumWidth(130)
|
||||
|
||||
self.downloadTitleLabel, self.uploadTitleLabel = (
|
||||
AppQLabel(translatable=False, parent=self),
|
||||
AppQLabel(translatable=False, parent=self),
|
||||
)
|
||||
|
||||
for titleLabel in (self.downloadTitleLabel, self.uploadTitleLabel):
|
||||
titleLabel.setObjectName('MetricsDirectionTitle')
|
||||
|
||||
self.downloadSpeedCard, self.downloadUsageCard = (
|
||||
_MetricCard(downloadSpeedGraph, parent=self),
|
||||
_MetricCard(downloadUsageGraph, parent=self),
|
||||
)
|
||||
|
||||
self.uploadSpeedCard, self.uploadUsageCard = (
|
||||
_MetricCard(uploadSpeedGraph, parent=self),
|
||||
_MetricCard(uploadUsageGraph, parent=self),
|
||||
)
|
||||
|
||||
headerLayout = QHBoxLayout()
|
||||
headerLayout.setContentsMargins(0, 0, 0, 0)
|
||||
headerLayout.setSpacing(8)
|
||||
headerLayout.addWidget(self.titleLabel)
|
||||
headerLayout.addStretch(1)
|
||||
headerLayout.addWidget(self.timeRangeLabel)
|
||||
headerLayout.addWidget(self.timeRangeComboBox)
|
||||
headerLayout.addSpacing(8)
|
||||
headerLayout.addWidget(self.granularityLabel)
|
||||
headerLayout.addWidget(self.granularityComboBox)
|
||||
|
||||
downloadLayout = QHBoxLayout()
|
||||
downloadLayout.setContentsMargins(0, 0, 0, 0)
|
||||
downloadLayout.setSpacing(12)
|
||||
downloadLayout.addWidget(self.downloadSpeedCard, 1)
|
||||
downloadLayout.addWidget(self.downloadUsageCard, 1)
|
||||
|
||||
uploadLayout = QHBoxLayout()
|
||||
uploadLayout.setContentsMargins(0, 0, 0, 0)
|
||||
uploadLayout.setSpacing(12)
|
||||
uploadLayout.addWidget(self.uploadSpeedCard, 1)
|
||||
uploadLayout.addWidget(self.uploadUsageCard, 1)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(16, 14, 16, 16)
|
||||
layout.setSpacing(10)
|
||||
layout.addWidget(self.titleLabel)
|
||||
layout.addLayout(graphLayout, 1)
|
||||
layout.addLayout(headerLayout)
|
||||
layout.addWidget(self.downloadTitleLabel)
|
||||
layout.addLayout(downloadLayout, 1)
|
||||
layout.addWidget(self.uploadTitleLabel)
|
||||
layout.addLayout(uploadLayout, 1)
|
||||
|
||||
def setTitles(self, sectionTitle, speedTitle, usageTitle):
|
||||
"""Set translated section and graph-card titles."""
|
||||
self.titleLabel.setText(sectionTitle)
|
||||
self.speedCard.setTitle(speedTitle)
|
||||
self.usageCard.setTitle(usageTitle)
|
||||
def setTitles(
|
||||
self,
|
||||
downloadTitle,
|
||||
downloadSpeedTitle,
|
||||
downloadUsageTitle,
|
||||
uploadTitle,
|
||||
uploadSpeedTitle,
|
||||
uploadUsageTitle,
|
||||
):
|
||||
"""Set translated direction and graph-card titles."""
|
||||
self.downloadTitleLabel.setText(downloadTitle)
|
||||
self.downloadSpeedCard.setTitle(downloadSpeedTitle)
|
||||
self.downloadUsageCard.setTitle(downloadUsageTitle)
|
||||
self.uploadTitleLabel.setText(uploadTitle)
|
||||
self.uploadSpeedCard.setTitle(uploadSpeedTitle)
|
||||
self.uploadUsageCard.setTitle(uploadUsageTitle)
|
||||
|
||||
|
||||
class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
@@ -136,34 +202,8 @@ class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
self._dirty = True
|
||||
self._renderRevision = 0
|
||||
|
||||
(
|
||||
self.pageTitleLabel,
|
||||
self.timeRangeLabel,
|
||||
self.granularityLabel,
|
||||
self.timeRangeComboBox,
|
||||
self.granularityComboBox,
|
||||
) = (
|
||||
AppQLabel(_('Network Metrics')),
|
||||
AppQLabel(_('Time Range')),
|
||||
AppQLabel(_('Granularity')),
|
||||
AppQComboBox(),
|
||||
AppQComboBox(),
|
||||
)
|
||||
|
||||
self.pageTitleLabel = AppQLabel(_('Network Metrics'))
|
||||
self.pageTitleLabel.setObjectName('MetricsPageTitle')
|
||||
self.timeRangeComboBox.setMinimumWidth(160)
|
||||
self.granularityComboBox.setMinimumWidth(130)
|
||||
|
||||
self._populateComboBox(
|
||||
self.timeRangeComboBox,
|
||||
self._timeRangeOptions(),
|
||||
self.DefaultTimeRange,
|
||||
)
|
||||
self._populateComboBox(
|
||||
self.granularityComboBox,
|
||||
self._granularityOptions(),
|
||||
self.DefaultGranularity,
|
||||
)
|
||||
|
||||
(
|
||||
self.downloadSpeedGraph,
|
||||
@@ -189,15 +229,35 @@ class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
),
|
||||
)
|
||||
|
||||
self.downloadSection, self.uploadSection = (
|
||||
_MetricsSection(
|
||||
self.downloadSpeedGraph,
|
||||
self.downloadUsageGraph,
|
||||
),
|
||||
_MetricsSection(
|
||||
self.uploadSpeedGraph,
|
||||
self.uploadUsageGraph,
|
||||
),
|
||||
self.metricsCard = _TrafficMetricsCard(
|
||||
self.downloadSpeedGraph,
|
||||
self.downloadUsageGraph,
|
||||
self.uploadSpeedGraph,
|
||||
self.uploadUsageGraph,
|
||||
parent=self,
|
||||
)
|
||||
|
||||
(
|
||||
self.timeRangeLabel,
|
||||
self.granularityLabel,
|
||||
self.timeRangeComboBox,
|
||||
self.granularityComboBox,
|
||||
) = (
|
||||
self.metricsCard.timeRangeLabel,
|
||||
self.metricsCard.granularityLabel,
|
||||
self.metricsCard.timeRangeComboBox,
|
||||
self.metricsCard.granularityComboBox,
|
||||
)
|
||||
|
||||
self._populateComboBox(
|
||||
self.timeRangeComboBox,
|
||||
self._timeRangeOptions(),
|
||||
self.DefaultTimeRange,
|
||||
)
|
||||
self._populateComboBox(
|
||||
self.granularityComboBox,
|
||||
self._granularityOptions(),
|
||||
self.DefaultGranularity,
|
||||
)
|
||||
|
||||
self.endpointInfoWidget = EndpointInfoWidget(
|
||||
@@ -210,26 +270,14 @@ class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
self._endpointInfoEnabledChanged
|
||||
)
|
||||
|
||||
controlsLayout = QHBoxLayout()
|
||||
controlsLayout.setContentsMargins(0, 0, 0, 0)
|
||||
controlsLayout.setSpacing(8)
|
||||
controlsLayout.addWidget(self.pageTitleLabel)
|
||||
controlsLayout.addStretch(1)
|
||||
controlsLayout.addWidget(self.timeRangeLabel)
|
||||
controlsLayout.addWidget(self.timeRangeComboBox)
|
||||
controlsLayout.addSpacing(8)
|
||||
controlsLayout.addWidget(self.granularityLabel)
|
||||
controlsLayout.addWidget(self.granularityComboBox)
|
||||
|
||||
contentWidget = QWidget()
|
||||
contentWidget.setObjectName('MetricsPageContent')
|
||||
|
||||
contentLayout = QVBoxLayout(contentWidget)
|
||||
contentLayout.setContentsMargins(20, 18, 20, 20)
|
||||
contentLayout.setSpacing(14)
|
||||
contentLayout.addLayout(controlsLayout)
|
||||
contentLayout.addWidget(self.downloadSection, 1)
|
||||
contentLayout.addWidget(self.uploadSection, 1)
|
||||
contentLayout.addWidget(self.pageTitleLabel)
|
||||
contentLayout.addWidget(self.metricsCard, 1)
|
||||
contentLayout.addWidget(self.endpointInfoWidget)
|
||||
|
||||
self.scrollArea = QScrollArea()
|
||||
@@ -237,6 +285,7 @@ class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
self.scrollArea.setWidgetResizable(True)
|
||||
self.scrollArea.setFrameShape(QFrame.Shape.NoFrame)
|
||||
self.scrollArea.setWidget(contentWidget)
|
||||
|
||||
self.setCentralWidget(self.scrollArea)
|
||||
|
||||
self._renderTimer = QtCore.QTimer(self)
|
||||
@@ -401,12 +450,10 @@ class MetricsPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
|
||||
def retranslate(self):
|
||||
"""Refresh composite section, graph, and endpoint presentation text."""
|
||||
self.downloadSection.setTitles(
|
||||
self.metricsCard.setTitles(
|
||||
_('Download'),
|
||||
_('Download Speed'),
|
||||
_('Download Traffic Usage'),
|
||||
)
|
||||
self.uploadSection.setTitles(
|
||||
_('Upload'),
|
||||
_('Upload Speed'),
|
||||
_('Upload Traffic Usage'),
|
||||
|
||||
Reference in New Issue
Block a user