Skip to content

Commit

Permalink
feat(disk): add group label functionality and container padding options
Browse files Browse the repository at this point in the history
- Introduced a new 'group_label' configuration to enable grouping of volume labels with customizable properties such as alignment, direction, and distance.
- Added 'container_padding' options to adjust the padding around the disk widget.
- Implemented a popup dialog to display grouped labels with disk usage information and a progress bar.
  • Loading branch information
amnweb committed Jan 5, 2025
1 parent b3d70bb commit 5972b1b
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 13 deletions.
48 changes: 48 additions & 0 deletions src/core/validation/widgets/yasb/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
'volume_label': "C",
'update_interval': 60,
'decimal_display': 1,
'group_label': {
'enabled': False,
'volume_labels': ['C'],
'blur': True,
'alignment': 'right',
'direction': 'down',
'distance': 6,
},
'container_padding': {'top': 0, 'left': 0, 'bottom': 0, 'right': 0},
'callbacks': {
'on_left': 'toggle_label',
'on_middle': 'do_nothing',
Expand Down Expand Up @@ -37,6 +46,45 @@
'min': 0,
'max': 3
},
'group_label': {
'type': 'dict',
'required': False,
'schema': {
'enabled': {
'type': 'boolean',
'default': DEFAULTS['group_label']['enabled']
},
'volume_labels': {
'type': 'list',
'schema': {
'type': 'string'
},
'default': DEFAULTS['group_label']['volume_labels']
},
'blur': {
'type': 'boolean',
'default': DEFAULTS['group_label']['blur']
},
'alignment': {
'type': 'string',
'default': DEFAULTS['group_label']['alignment']
},
'direction': {
'type': 'string',
'default': DEFAULTS['group_label']['direction']
},
'distance': {
'type': 'integer',
'default': DEFAULTS['group_label']['distance']
}
},
'default': DEFAULTS['group_label']
},
'container_padding': {
'type': 'dict',
'default': DEFAULTS['container_padding'],
'required': False
},
'callbacks': {
'type': 'dict',
'schema': {
Expand Down
173 changes: 160 additions & 13 deletions src/core/widgets/yasb/disk.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
import os
import psutil
import re
from core.widgets.base import BaseWidget
from core.validation.widgets.yasb.disk import VALIDATION_SCHEMA
from PyQt6.QtWidgets import QLabel, QHBoxLayout, QWidget
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QLabel, QHBoxLayout, QWidget, QDialog, QProgressBar, QVBoxLayout, QApplication
from PyQt6.QtCore import Qt, QPoint, pyqtSignal, QEvent
from core.utils.win32.blurWindow import Blur
from core.utils.utilities import is_windows_10

class PopupWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
QApplication.instance().installEventFilter(self)

def eventFilter(self, obj, event):
if event.type() == QEvent.Type.MouseButtonPress:
global_pos = event.globalPosition().toPoint()
if not self.geometry().contains(global_pos):
self.hide()
return True
return super().eventFilter(obj, event)

def hideEvent(self, event):
QApplication.instance().removeEventFilter(self)
super().hideEvent(event)


class ClickableDiskWidget(QWidget):
clicked = pyqtSignal()

def __init__(self, label, parent=None):
super().__init__(parent)
self.label = label

def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.clicked.emit()
super().mousePressEvent(event)

class DiskWidget(BaseWidget):
validation_schema = VALIDATION_SCHEMA

Expand All @@ -15,6 +48,8 @@ def __init__(
volume_label: str,
decimal_display: int,
update_interval: int,
group_label: dict[str, str],
container_padding: dict[str, int],
callbacks: dict[str, str],
):
super().__init__(int(update_interval * 1000), class_name="disk-widget")
Expand All @@ -23,11 +58,13 @@ def __init__(
self._label_content = label
self._label_alt_content = label_alt
self._volume_label = volume_label.upper()

self._padding = container_padding
self._group_label = group_label

# Construct container
self._widget_container_layout: QHBoxLayout = QHBoxLayout()
self._widget_container_layout.setSpacing(0)
self._widget_container_layout.setContentsMargins(0, 0, 0, 0)
self._widget_container_layout.setContentsMargins(self._padding['left'],self._padding['top'],self._padding['right'],self._padding['bottom'])
# Initialize container
self._widget_container: QWidget = QWidget()
self._widget_container.setLayout(self._widget_container_layout)
Expand All @@ -43,9 +80,15 @@ def __init__(
self.callback_right = callbacks['on_right']
self.callback_middle = callbacks['on_middle']
self.callback_timer = "update_label"
self.start_timer()

if not self._group_label['enabled']:
self.start_timer()



def _toggle_label(self):
if self._group_label['enabled']:
self.show_group_label()
return
self._show_alt_label = not self._show_alt_label
for widget in self._widgets:
widget.setVisible(not self._show_alt_label)
Expand All @@ -59,7 +102,7 @@ def process_content(content, is_alt=False):
label_parts = [part for part in label_parts if part]
widgets = []
for part in label_parts:
part = part.strip() # Remove any leading/trailing whitespace
part = part.strip()
if not part:
continue
if '<span' in part and '</span>' in part:
Expand All @@ -71,7 +114,9 @@ def process_content(content, is_alt=False):
else:
label = QLabel(part)
label.setProperty("class", "label")
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
if self._group_label['enabled']:
label.setCursor(Qt.CursorShape.PointingHandCursor)
self._widget_container_layout.addWidget(label)
widgets.append(label)
if is_alt:
Expand Down Expand Up @@ -107,12 +152,114 @@ def _update_label(self):
active_widgets[widget_index].setText(formatted_text)
widget_index += 1



def show_group_label(self):
self.dialog = PopupWidget(self)
self.dialog.setProperty("class", "disk-group")
self.dialog.setWindowFlag(Qt.WindowType.FramelessWindowHint)
self.dialog.setWindowFlag(Qt.WindowType.Popup)
layout = QVBoxLayout()
for label in self._group_label['volume_labels']:
disk_space = self._get_space(label)
if disk_space is None:
continue
row_widget = QWidget()
row_widget.setProperty("class", "disk-group-row")

clicable_row = ClickableDiskWidget(label)
clicable_row.clicked.connect(lambda lbl=label: self.open_explorer(lbl))
clicable_row.setCursor(Qt.CursorShape.PointingHandCursor)

v_layout = QVBoxLayout(clicable_row)
h_layout = QHBoxLayout()

label_widget = QLabel(f"{label}:")
label_widget.setProperty("class", "disk-group-label")
h_layout.addWidget(label_widget)

def _get_space(self):
partitions = psutil.disk_partitions()
specific_partitions = [partition for partition in partitions if partition.device in (f'{self._volume_label}:\\')]
label_size = QLabel()
label_size.setProperty("class", "disk-group-label-size")

# show size in TB if it's more than 1000GB
total_gb = float(disk_space['total']['gb'].strip('GB'))
free_gb = float(disk_space['free']['gb'].strip('GB'))
if total_gb > 1000:
total_size = disk_space['total']['tb']
else:
total_size = disk_space['total']['gb']

if free_gb > 1000:
free_size = disk_space['free']['tb']
else:
free_size = disk_space['free']['gb']
label_size.setText(f"{free_size} / {total_size}")
h_layout.addStretch()
h_layout.addWidget(label_size)

v_layout.addLayout(h_layout)

progress_bar = QProgressBar()
progress_bar.setTextVisible(False)
progress_bar.setProperty("class", "disk-group-label-bar")
if disk_space:
progress_bar.setValue(int(float(disk_space['used']['percent'].strip('%'))))
v_layout.addWidget(progress_bar)

row_widget_layout = QVBoxLayout(row_widget)
row_widget_layout.setContentsMargins(0, 0, 0, 0)
row_widget_layout.setSpacing(0)
row_widget_layout.addWidget(clicable_row)

layout.addWidget(row_widget)

self.dialog.setLayout(layout)

if self._group_label['blur']:
Blur(
self.dialog.winId(),
Acrylic=True if is_windows_10() else False,
DarkMode=False,
RoundCorners=True,
BorderColor="System"
)

# Position the dialog
self.dialog.adjustSize()
widget_global_pos = self.mapToGlobal(QPoint(0, self.height() + self._group_label['distance']))
if self._group_label['direction'] == 'up':
global_y = self.mapToGlobal(QPoint(0, 0)).y() - self.dialog.height() - self._group_label['distance']
widget_global_pos = QPoint(self.mapToGlobal(QPoint(0, 0)).x(), global_y)

if self._group_label['alignment'] == 'left':
global_position = widget_global_pos
elif self._group_label['alignment'] == 'right':
global_position = QPoint(
widget_global_pos.x() + self.width() - self.dialog.width(),
widget_global_pos.y()
)
elif self._group_label['alignment'] == 'center':
global_position = QPoint(
widget_global_pos.x() + (self.width() - self.dialog.width()) // 2,
widget_global_pos.y()
)
else:
global_position = widget_global_pos

self.dialog.move(global_position)
self.dialog.show()

def open_explorer(self, label):
os.startfile(f"{label}:\\")

def _get_space(self, volume_label=None):
if volume_label is None:
volume_label = self._volume_label

partitions = psutil.disk_partitions()
specific_partitions = [partition for partition in partitions if partition.device in (f'{volume_label}:\\')]
if not specific_partitions:
return

for partition in specific_partitions:
usage = psutil.disk_usage(partition.mountpoint)
percent_used = usage.percent
Expand All @@ -136,4 +283,4 @@ def _get_space(self):
'percent': f"{percent_used:.{self._decimal_display}f}%"
}
}
return None
return None

0 comments on commit 5972b1b

Please sign in to comment.