Skip to content

Commit

Permalink
Merge pull request #110 from FrnkPsycho/traffic_widget
Browse files Browse the repository at this point in the history
feat: add network traffic widget and some fixes
  • Loading branch information
da-rth authored Nov 11, 2023
2 parents e10b786 + d218a4f commit f4b7a1f
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 21 deletions.
8 changes: 8 additions & 0 deletions src/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,14 @@ widgets:
on_middle: "do_nothing"
on_right: "exec cmd.exe /c start ms-settings:network"

traffic:
type: "yasb.traffic.TrafficWidget"
options:
label: "\ueb01 \ueab4 {download_speed} | \ueab7 {upload_speed}"
label_alt: "\ueb01 \ueab4 {upload_speed} | \ueab7 {download_speed}"
update_interval: 1000 # Update interval should be a multiple of 1000
callbacks:
on_right: "exec cmd /c Taskmgr"

# Some custom widgets

Expand Down
39 changes: 39 additions & 0 deletions src/core/validation/widgets/yasb/traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
DEFAULTS = {
"label": "\ueb01 \ueab4 {download_speed} | \ueab7 {upload_speed}",
"label_alt": "\ueb01 \ueab4 {upload_speed} | \ueab7 {download_speed}",
"update_interval": 1000,
"callbacks": {
"on_left": "toggle_label",
"on_middle": "do_nothing",
"on_right": "do_nothing",
},
}

VALIDATION_SCHEMA = {
"label": {"type": "string", "default": DEFAULTS["label"]},
"label_alt": {"type": "string", "default": DEFAULTS["label_alt"]},
"update_interval": {
"type": "integer",
"default": DEFAULTS["update_interval"],
"min": 0,
"max": 60000,
},
"callbacks": {
"type": "dict",
"schema": {
"on_left": {
"type": "string",
"default": DEFAULTS["callbacks"]["on_left"],
},
"on_middle": {
"type": "string",
"default": DEFAULTS["callbacks"]["on_middle"],
},
"on_right": {
"type": "string",
"default": DEFAULTS["callbacks"]["on_right"],
},
},
"default": DEFAULTS["callbacks"],
},
}
2 changes: 0 additions & 2 deletions src/core/validation/widgets/yasb/wifi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
DEFAULTS = {
# 'label': '\uf017 {%H:%M:%S}',
# 'label_alt': '\uf017 {%d-%m-%y %H:%M:%S}',
'label': "{wifi_icon}",
'label_alt': "{wifi_icon} {wifi_name}",
'update_interval': 1000,
Expand Down
2 changes: 2 additions & 0 deletions src/core/widgets/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ def __init__(
self._label_alt.setProperty("class", "label alt")
self.widget_layout.addWidget(self._label)
self.widget_layout.addWidget(self._label_alt)

self.register_callback("toggle_label", self._toggle_label)
self.register_callback("update_label", self._update_label)

self.callback_left = callbacks['on_left']
self.callback_right = callbacks['on_right']
Expand Down
105 changes: 105 additions & 0 deletions src/core/widgets/yasb/traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import psutil
from humanize import naturalsize
from core.widgets.base import BaseWidget
from core.validation.widgets.yasb.traffic import VALIDATION_SCHEMA
from PyQt6.QtWidgets import QLabel


class TrafficWidget(BaseWidget):
validation_schema = VALIDATION_SCHEMA

# initialize io counters
io = psutil.net_io_counters()
bytes_sent = io.bytes_sent
bytes_recv = io.bytes_recv
interval = 1 # second(s)

def __init__(
self,
label: str,
label_alt: str,
update_interval: int,
callbacks: dict[str, str],
):
super().__init__(update_interval, class_name="traffic-widget")
self.interval = update_interval // 1000

self._show_alt_label = False
self._label_content = label
self._label_alt_content = label_alt

self._label = QLabel()
self._label_alt = QLabel()
self._label.setProperty("class", "label")
self._label_alt.setProperty("class", "label alt")
self.widget_layout.addWidget(self._label)
self.widget_layout.addWidget(self._label_alt)

self.register_callback("toggle_label", self._toggle_label)
self.register_callback("update_label", self._update_label)

self.callback_left = callbacks["on_left"]
self.callback_right = callbacks["on_right"]
self.callback_middle = callbacks["on_middle"]
self.callback_timer = "update_label"

self._label.show()
self._label_alt.hide()

self.start_timer()

def _toggle_label(self):
self._show_alt_label = not self._show_alt_label

if self._show_alt_label:
self._label.hide()
self._label_alt.show()
else:
self._label.show()
self._label_alt.hide()

self._update_label()

def _update_label(self):
# Update the active label at each timer interval
active_label = self._label_alt if self._show_alt_label else self._label
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
active_label_formatted = active_label_content

try:
upload_speed, download_speed = self._get_speed()
except Exception:
upload_speed, download_speed = "N/A", "N/A"

label_options = [
("{upload_speed}", upload_speed),
("{download_speed}", download_speed),
]

for option, value in label_options:
active_label_formatted = active_label_formatted.replace(option, str(value))

active_label.setText(active_label_formatted)

def _get_speed(self) -> [str, str]:
current_io = psutil.net_io_counters()
upload_diff = current_io.bytes_sent - self.bytes_sent
download_diff = current_io.bytes_recv - self.bytes_recv

if upload_diff < 1024:
upload_speed = f"{upload_diff} B/s"
else:
upload_speed = naturalsize(
(current_io.bytes_sent - self.bytes_sent) // self.interval,
) + "/s"

if download_diff < 1024:
download_speed = f"{download_diff} B/s"
else:
download_speed = naturalsize(
(current_io.bytes_recv - self.bytes_recv) // self.interval,
) + "/s"

self.bytes_sent = current_io.bytes_sent
self.bytes_recv = current_io.bytes_recv
return upload_speed, download_speed
45 changes: 26 additions & 19 deletions src/core/widgets/yasb/wifi.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class WifiWidget(BaseWidget):
validation_schema = VALIDATION_SCHEMA

def __init__(
self,
label: str,
label_alt: str,
update_interval: int,
wifi_icons: list[str],
callbacks: dict[str, str],
self,
label: str,
label_alt: str,
update_interval: int,
wifi_icons: list[str],
callbacks: dict[str, str],
):
super().__init__(update_interval, class_name="wifi-widget")
self._wifi_icons = wifi_icons
Expand All @@ -32,9 +32,9 @@ def __init__(
self.register_callback("toggle_label", self._toggle_label)
self.register_callback("update_label", self._update_label)

self.callback_left = callbacks['on_left']
self.callback_right = callbacks['on_right']
self.callback_middle = callbacks['on_middle']
self.callback_left = callbacks["on_left"]
self.callback_right = callbacks["on_right"]
self.callback_middle = callbacks["on_middle"]
self.callback_timer = "update_label"

self._label.show()
Expand All @@ -61,33 +61,40 @@ def _update_label(self):
# Determine which label is active
active_label = self._label_alt if self._show_alt_label else self._label

if self._show_alt_label:
updated_content = f"{wifi_icon} {wifi_name}"
else:
updated_content = f"{wifi_icon}"
label_options = [
("{wifi_icon}", wifi_icon),
("{wifi_name}", wifi_name),
]

# Format the label content
updated_content = self._label_alt_content if self._show_alt_label else self._label_content
for label_option in label_options:
updated_content = updated_content.replace(
label_option[0], str(label_option[1])
)

active_label.setText(updated_content)

def _get_wifi_strength(self):
# Get the wifi strength from the system
result = result = os.popen('netsh wlan show interfaces').read()
result = os.popen("netsh wlan show interfaces").read()

# Return 0 if no wifi interface is found
if "There is no wireless interface on the system." in result:
return 0

# Extract signal strength from the result
for line in result.split('\n'):
if "Signal" in line:
strength = line.split(":")[1].strip().split(' ')[0].replace('%', '')
for line in result.split("\n"):
if "Signal" in line: # FIXME: This will break if the system language is not English
strength = line.split(":")[1].strip().split(" ")[0].replace("%", "")
return int(strength)

return 0

def _get_wifi_name(self):
result = result = os.popen('netsh wlan show interfaces').read()
result = os.popen("netsh wlan show interfaces").read()

for line in result.split('\n'):
for line in result.split("\n"):
if "SSID" in line:
return line.split(":")[1].strip()

Expand Down
5 changes: 5 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,17 @@
.cpu-widget .label,
.wifi-widget .label,
.memory-widget .label,
.traffic-widget .label,
.battery-widget .label {
padding: 2px 5px;
font-size: 14px;
border-radius: 5px;
}

.traffic-widget .label {
background: #B3D3D9;
}

.wifi-widget .label {
background: #b8bb26;
}
Expand Down

0 comments on commit f4b7a1f

Please sign in to comment.