diff --git a/src/core/widgets/glazewm/binding_mode.py b/src/core/widgets/glazewm/binding_mode.py index b5a3f3a9..ceac4181 100644 --- a/src/core/widgets/glazewm/binding_mode.py +++ b/src/core/widgets/glazewm/binding_mode.py @@ -107,34 +107,29 @@ def _reload_css(self, label: QLabel): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + + active_label_content = active_label_content.format( + binding_mode=( + self._active_binding_mode.display_name or self._active_binding_mode.name or self._label_if_no_active + ), + icon=self._icons.get(self._active_binding_mode.name or "none", self._default_icon), + ) + label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 - label_options = { - "{binding_mode}": self._active_binding_mode.display_name - or self._active_binding_mode.name - or self._label_if_no_active, - "{icon}": self._icons.get(self._active_binding_mode.name or "none", self._default_icon), - } for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: - icon = re.sub(r"|", "", part).strip() - if icon in label_options: - active_widgets[widget_index].setProperty( - "class", f"icon {self._active_binding_mode.name or 'none'}" - ) - active_widgets[widget_index].setText(formatted_text) - else: - active_widgets[widget_index].setText(icon) + part = re.sub(r"|", "", part).strip() + active_widgets[widget_index].setProperty( + "class", f"icon {self._active_binding_mode.name or 'none'}" + ) + active_widgets[widget_index].setText(part) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) if active_widgets[widget_index].property("class") == "label-offline": active_widgets[widget_index].setProperty("class", "label") if not self._active_binding_mode.name: diff --git a/src/core/widgets/yasb/battery.py b/src/core/widgets/yasb/battery.py index d9222a57..8f979ef3 100644 --- a/src/core/widgets/yasb/battery.py +++ b/src/core/widgets/yasb/battery.py @@ -144,9 +144,8 @@ def _charging_blink(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 + self._battery_state = psutil.sensors_battery() if self._battery_state is None: @@ -155,8 +154,13 @@ def _update_label(self): self.timer.stop() return + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() + if not part: + continue + if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): if "" in part: active_widgets[widget_index].hide() @@ -170,19 +174,21 @@ def _update_label(self): is_charging_str = "yes" if self._battery_state.power_plugged else "no" charging_icon = self._get_charging_icon(original_threshold) + active_label_content = active_label_content.format( + percent=str(self._battery_state.percent), + time_remaining=time_remaining, + is_charging=is_charging_str, + icon=charging_icon, + ) + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - battery_status = ( - part.replace("{percent}", str(self._battery_state.percent)) - .replace("{time_remaining}", time_remaining) - .replace("{is_charging}", is_charging_str) - .replace("{icon}", charging_icon) - ) - if "" in battery_status: + if "" in part: # icon-only QLabel widget_label = active_widgets[widget_index] - icon = re.sub(r"|", "", battery_status).strip() + icon = re.sub(r"|", "", part).strip() widget_label.setText(icon) # apply status‐class existing_classes = widget_label.property("class") @@ -207,8 +213,7 @@ def _update_label(self): refresh_widget_style(widget_label) else: alt_class = "alt" if self._show_alt_label else "" - formatted_text = battery_status.format(battery_status) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) active_widgets[widget_index].setProperty("class", f"label {alt_class} status-{threshold}") refresh_widget_style(active_widgets[widget_index]) widget_index += 1 diff --git a/src/core/widgets/yasb/bluetooth.py b/src/core/widgets/yasb/bluetooth.py index 97bebde1..850bf1cf 100644 --- a/src/core/widgets/yasb/bluetooth.py +++ b/src/core/widgets/yasb/bluetooth.py @@ -310,8 +310,6 @@ def _toggle_label(self): def _update_label(self, icon, connected_devices=None): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 if connected_devices: @@ -333,26 +331,25 @@ def _update_label(self, icon, connected_devices=None): device_names = self._label_no_device tooltip_text = self._label_no_device - label_options = { - "{icon}": icon, - "{device_name}": device_names, - "{device_count}": len(connected_devices) if connected_devices else 0, - } + active_label_content = active_label_content.format( + icon=icon, + device_name=device_names, + device_count=len(connected_devices) if connected_devices else 0, + ) + + label_parts = re.split("(.*?)", active_label_content) for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) else: - if self._max_length and len(formatted_text) > self._max_length: - formatted_text = formatted_text[: self._max_length] + self._max_length_ellipsis + if self._max_length and len(part) > self._max_length: + part = part[: self._max_length] + self._max_length_ellipsis if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 if self._tooltip: diff --git a/src/core/widgets/yasb/brightness.py b/src/core/widgets/yasb/brightness.py index da3e02dc..403955ff 100644 --- a/src/core/widgets/yasb/brightness.py +++ b/src/core/widgets/yasb/brightness.py @@ -158,9 +158,7 @@ def _toggle_brightness_menu(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] - widget_index = 0 + try: percent = self.get_brightness() if percent is None: @@ -176,7 +174,9 @@ def _update_label(self): except Exception: percent, icon = 0, "not supported" - label_options = {"{icon}": icon, "{percent}": percent} + active_label_content = active_label_content.format(icon=icon, percent=percent) + label_parts = re.split("(.*?)", active_label_content) + widget_index = 0 if self._progress_bar["enabled"] and self.progress_widget: if self._widget_container_layout.indexOf(self.progress_widget) == -1: @@ -189,15 +189,12 @@ def _update_label(self): for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 def show_brightness_menu(self): diff --git a/src/core/widgets/yasb/clock.py b/src/core/widgets/yasb/clock.py index 903662c4..8a694756 100644 --- a/src/core/widgets/yasb/clock.py +++ b/src/core/widgets/yasb/clock.py @@ -511,16 +511,33 @@ def _update_label(self): # Choose which label set to update (primary or alternate) active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 + now = datetime.now(ZoneInfo(self._active_tz)) if self._active_tz else datetime.now().astimezone() + + # Finding the datetime format string in the label using keyerror exception. + try: + active_label_content.format(icon="", alarm="", timedata=now) + except KeyError as ke: + # Remove the quotes around the exception message to get the datetime format. + datetime_format = str(ke)[1:-1] + + datetime_format_idx = active_label_content.find(datetime_format) + closing_braces_idx = active_label_content.find("}", datetime_format_idx + len(datetime_format)) + + datetime_format = active_label_content[datetime_format_idx:closing_braces_idx] + active_label_content = active_label_content.replace( + "{" + datetime_format + "}", now.strftime(datetime_format) + ) + current_hour = f"{now.hour:02d}" current_minute = f"{now.minute:02d}" hour_changed = self._current_hour != current_hour minute_changed = self._current_minute != current_minute + if hour_changed: self._current_hour = current_hour + if minute_changed: self._current_minute = current_minute @@ -539,72 +556,53 @@ def _update_label(self): self._timer_label.hide() self._timer_visible = False + clock_icon = self._get_icon_for_hour(now.hour) + hour_class = f"clock_{current_hour}" + alarm_icon = alarm_class = "" + + if self._shared_state._snoozed_alarms: + alarm_class = "icon alarm snooze" + alarm_icon = self._alarm_icons["snooze"] + + elif self._has_enabled_alarms(): + alarm_icon = self._alarm_icons["enabled"] + alarm_class = "icon alarm" + + # The icon place holders are replaced with a span tag of the icon string, with all of its appropriate classes + # assigned to it. + label_content_values = { + "icon": f'{clock_icon}', + "alarm": f'{alarm_icon}', + "timedata": now, + } + + active_label_content = active_label_content.format_map(label_content_values) + + # If any of the icon placeholders are already in a span tag, then flatten the 2 layers of nested span tags, and + # merge their classes into one span tag, before sending them for parsing. + active_label_content = re.sub( + r'[\w -]*)\1)?>[\w -]*)\3>(?P.*?)', + r'\g', + active_label_content, + ) + + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): if "" in part: + match = re.search(r'[\w -]*)\1>[^>]*', part) + classes = match.group("class_name") or "" + icon_placeholder = re.sub(r"|", "", part).strip() - if icon_placeholder == "{icon}": - if hour_changed: - icon = self._get_icon_for_hour(now.hour) - active_widgets[widget_index].setText(icon) - hour_class = f"clock_{current_hour}" - active_widgets[widget_index].setProperty("class", f"icon {hour_class}") - refresh_widget_style(active_widgets[widget_index]) - elif icon_placeholder == "{alarm}": - if self._shared_state._snoozed_alarms: - active_widgets[widget_index].setText(self._alarm_icons["snooze"]) - active_widgets[widget_index].setProperty("class", "icon alarm snooze") - active_widgets[widget_index].setVisible(True) - refresh_widget_style(active_widgets[widget_index]) - elif self._has_enabled_alarms(): - active_widgets[widget_index].setText(self._alarm_icons["enabled"]) - active_widgets[widget_index].setProperty("class", "icon alarm") - active_widgets[widget_index].setVisible(True) - refresh_widget_style(active_widgets[widget_index]) - else: - active_widgets[widget_index].setText("") - active_widgets[widget_index].setVisible(False) - - else: - active_widgets[widget_index].setText(icon_placeholder) - else: - has_alarm = "{alarm}" in part and (self._shared_state._snoozed_alarms or self._has_enabled_alarms()) - - if "{icon}" in part: - icon = self._get_icon_for_hour(now.hour) - part = part.replace("{icon}", icon) - - if "{alarm}" in part: - if self._shared_state._snoozed_alarms: - part = part.replace("{alarm}", self._alarm_icons["snooze"]) - elif self._has_enabled_alarms(): - part = part.replace("{alarm}", self._alarm_icons["enabled"]) - else: - part = part.replace("{alarm}", "") - try: - datetime_format_search = re.search(r"\{(.*)}", part) - datetime_format_str = datetime_format_search.group() - datetime_format = datetime_format_search.group(1) - format_label_content = part.replace(datetime_format_str, now.strftime(datetime_format)) - except Exception: - format_label_content = part - - active_widgets[widget_index].setText(format_label_content) - - alarm_state_changed = has_alarm != self._previous_alarm_state - if has_alarm: - if self._shared_state._snoozed_alarms: - active_widgets[widget_index].setProperty("class", "label alarm snooze") - else: - active_widgets[widget_index].setProperty("class", "label alarm") - refresh_widget_style(active_widgets[widget_index]) - else: - hour_class = f"clock_{current_hour}" - active_widgets[widget_index].setProperty("class", f"label {hour_class}") - if hour_changed or alarm_state_changed: - refresh_widget_style(active_widgets[widget_index]) + active_widgets[widget_index].setText(icon_placeholder) + active_widgets[widget_index].setProperty("class", classes.strip()) + refresh_widget_style(active_widgets[widget_index]) + else: + active_widgets[widget_index].setText(part) + has_alarm = self._shared_state._snoozed_alarms or self._has_enabled_alarms() self._previous_alarm_state = has_alarm widget_index += 1 diff --git a/src/core/widgets/yasb/cpu.py b/src/core/widgets/yasb/cpu.py index 635755b1..a2b8f7fa 100644 --- a/src/core/widgets/yasb/cpu.py +++ b/src/core/widgets/yasb/cpu.py @@ -164,8 +164,10 @@ def _update_label(self, cpu_freq, cpu_stats, current_perc, cores_perc, cpu_cores active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format(info=cpu_info) + cpu_threshold_class = self._get_cpu_threshold(current_perc) + label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 if self._progress_bar["enabled"] and self.progress_widget: @@ -184,12 +186,8 @@ def _update_label(self, cpu_freq, cpu_stats, current_perc, cores_perc, cpu_cores active_widgets[widget_index].setText(icon) else: label_class = "label alt" if self._show_alt_label else "label" - formatted_text = part.format(info=cpu_info) - active_widgets[widget_index].setText(formatted_text) - active_widgets[widget_index].setProperty("class", label_class) - active_widgets[widget_index].setProperty( - "class", f"{label_class} status-{self._get_cpu_threshold(current_perc)}" - ) + active_widgets[widget_index].setText(part) + active_widgets[widget_index].setProperty("class", f"{label_class} status-{cpu_threshold_class}") refresh_widget_style(active_widgets[widget_index]) widget_index += 1 diff --git a/src/core/widgets/yasb/custom.py b/src/core/widgets/yasb/custom.py index 0e7559b9..a8a608d8 100644 --- a/src/core/widgets/yasb/custom.py +++ b/src/core/widgets/yasb/custom.py @@ -180,8 +180,18 @@ def _truncate_label(self, label): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format(data=self._exec_data) label_parts = re.split("(.*?)", active_label_content) widget_index = 0 + + if self._hide_empty: + if self._exec_data: + self.setVisible(True) + # active_widgets[widget_index].show() + else: + self.setVisible(False) + # active_widgets[widget_index].hide() + try: for part in label_parts: part = part.strip() @@ -190,18 +200,18 @@ def _update_label(self): icon = re.sub(r"|", "", part).strip() active_widgets[widget_index].setText(icon) else: - active_widgets[widget_index].setText(self._truncate_label(part.format(data=self._exec_data))) - if self._hide_empty: - if self._exec_data: - self.setVisible(True) - # active_widgets[widget_index].show() - else: - self.setVisible(False) - # active_widgets[widget_index].hide() + active_widgets[widget_index].setText(self._truncate_label(part)) + + if not active_widgets[widget_index].isVisible(): + active_widgets[widget_index].setVisible(True) widget_index += 1 except Exception: active_widgets[widget_index].setText(self._truncate_label(part)) + while widget_index < len(active_widgets): + active_widgets[widget_index].setVisible(False) + widget_index += 1 + # Update tooltip if enabled self._update_tooltip() diff --git a/src/core/widgets/yasb/disk.py b/src/core/widgets/yasb/disk.py index 809741b3..525e601e 100644 --- a/src/core/widgets/yasb/disk.py +++ b/src/core/widgets/yasb/disk.py @@ -110,8 +110,6 @@ def _toggle_group(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 try: @@ -127,6 +125,8 @@ def _update_label(self): else: percent_value = float(percent_str) + active_label_content = active_label_content.format(space=disk_space, volume_label=self._volume_label) + if self._progress_bar["enabled"] and self.progress_widget: if self._widget_container_layout.indexOf(self.progress_widget) == -1: self._widget_container_layout.insertWidget( @@ -136,6 +136,9 @@ def _update_label(self): self.progress_widget.set_value(percent_value) + label_parts = re.split("(.*?)", active_label_content) + disk_threshold_class = self._get_disk_threshold(percent_value) + for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): @@ -146,13 +149,8 @@ def _update_label(self): else: # Update label with formatted content label_class = "label alt" if self._show_alt_label else "label" - formatted_text = ( - part.format(space=disk_space, volume_label=self._volume_label) if disk_space else part - ) - active_widgets[widget_index].setProperty( - "class", f"{label_class} status-{self._get_disk_threshold(percent_value)}" - ) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setProperty("class", f"{label_class} status-{disk_threshold_class}") + active_widgets[widget_index].setText(part) refresh_widget_style(active_widgets[widget_index]) widget_index += 1 diff --git a/src/core/widgets/yasb/github.py b/src/core/widgets/yasb/github.py index 7d794af9..2ff705f3 100644 --- a/src/core/widgets/yasb/github.py +++ b/src/core/widgets/yasb/github.py @@ -231,11 +231,13 @@ def _on_data_update(self, _notifications: list): def _update_label(self): github_data = GitHubDataManager.get_data() - notification_count = len([notification for notification in github_data if notification["unread"]]) + notification_count = sum(notification["unread"] for notification in github_data) active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format(data=notification_count) + # Split label content and filter out empty parts - label_parts = [part.strip() for part in re.split(r"(.*?)", active_label_content) if part] + label_parts = re.split(r"(.*?)", active_label_content) # Setting the notification dot if enabled and the label exists if self._notification_dot["enabled"]: @@ -244,8 +246,11 @@ def _update_label(self): if self._show_alt_label and self._notification_label_alt is not None: self._notification_label_alt.show_dot(notification_count > 0) - for widget_index, part in enumerate(label_parts): - if widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): + widget_index = 0 + + for part in label_parts: + part = part.strip() + if not part or widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): continue current_widget = active_widgets[widget_index] @@ -266,8 +271,9 @@ def _update_label(self): current_widget.setProperty("class", " ".join(current_classes)) else: - formatted_text = part.format(data=notification_count) - current_widget.setText(formatted_text) + current_widget.setText(part) + + widget_index += 1 refresh_widget_style(current_widget) def mark_as_read(self, notification_id, container_label): diff --git a/src/core/widgets/yasb/glucose_monitor.py b/src/core/widgets/yasb/glucose_monitor.py index 4ed8d8ac..aed6e1ef 100644 --- a/src/core/widgets/yasb/glucose_monitor.py +++ b/src/core/widgets/yasb/glucose_monitor.py @@ -158,16 +158,12 @@ def _open_cgm(self) -> None: webbrowser.open(self._host) def _update_label(self) -> None: + has_error_message = bool(self._error_message) + for widget in self._widgets: - widget.setVisible(not self._error_message) + widget.setVisible(not has_error_message) for widget in self._widgets_alt: - widget.setVisible(bool(self._error_message)) - - active_widgets = self._error_message and self._widgets_alt or self._widgets - active_label_content = self._error_message and self._error_label_content or self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = list(filter(None, label_parts)) - widget_index = 0 + widget.setVisible(has_error_message) format_data = ( self._error_message @@ -177,6 +173,13 @@ def _update_label(self) -> None: or self._status_data ) + active_widgets = self._error_message and self._widgets_alt or self._widgets + active_label_content = self._error_message and self._error_label_content or self._label_content + active_label_content = active_label_content.format_map(format_data) + label_parts = re.split("(.*?)", active_label_content) + label_parts = list(filter(None, label_parts)) + widget_index = 0 + for part in label_parts: part = part.strip() if not part or widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): @@ -184,7 +187,7 @@ def _update_label(self) -> None: if "" in part: icon = re.sub(r"|", "", part).strip() - active_widgets[widget_index].setText(icon.format_map(format_data)) + active_widgets[widget_index].setText(icon) current_class = active_widgets[widget_index].property("class") or "" if "sgv" in current_class.split(): @@ -192,8 +195,7 @@ def _update_label(self) -> None: active_widgets[widget_index].setProperty("class", new_class) refresh_widget_style(active_widgets[widget_index]) else: - formatted_text = part.format_map(format_data) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 if self._tooltip: diff --git a/src/core/widgets/yasb/gpu.py b/src/core/widgets/yasb/gpu.py index c71313e9..2312da91 100644 --- a/src/core/widgets/yasb/gpu.py +++ b/src/core/widgets/yasb/gpu.py @@ -196,8 +196,8 @@ def _update_label(self, gpu_data): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format(info=gpu_info) label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 if self._progress_bar["enabled"] and self.progress_widget: @@ -216,8 +216,7 @@ def _update_label(self, gpu_data): active_widgets[widget_index].setText(icon) else: label_class = "label alt" if self._show_alt_label else "label" - formatted_text = part.format(info=gpu_info) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) active_widgets[widget_index].setProperty("class", label_class) active_widgets[widget_index].setProperty( "class", f"{label_class} status-{self._get_gpu_threshold(gpu_data.utilization)}" diff --git a/src/core/widgets/yasb/language.py b/src/core/widgets/yasb/language.py index 3f6a97b7..5d85803d 100644 --- a/src/core/widgets/yasb/language.py +++ b/src/core/widgets/yasb/language.py @@ -11,10 +11,7 @@ from core.utils.utilities import PopupWidget, add_shadow, build_widget_label from core.utils.widgets.animation_manager import AnimationManager -from core.utils.win32.bindings import ( - kernel32, - user32, -) +from core.utils.win32.bindings import kernel32, user32 from core.utils.win32.constants import ( LOCALE_NAME_MAX_LENGTH, LOCALE_SCOUNTRY, @@ -108,13 +105,13 @@ def _toggle_menu(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 try: - lang = self._get_current_keyboard_language() + active_label_content = active_label_content.format(lang=self._get_current_keyboard_language()) except: - lang = None + pass + + label_parts = re.split("(.*?)", active_label_content) for part in label_parts: part = part.strip() @@ -125,8 +122,7 @@ def _update_label(self): active_widgets[widget_index].setText(icon) else: # Update label with formatted content - formatted_text = part.format(lang=lang) if lang else part - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 def _on_settings_click(self, event): diff --git a/src/core/widgets/yasb/libre_monitor.py b/src/core/widgets/yasb/libre_monitor.py index b7ea726b..7362c15a 100644 --- a/src/core/widgets/yasb/libre_monitor.py +++ b/src/core/widgets/yasb/libre_monitor.py @@ -280,8 +280,8 @@ def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format(info=info) label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 for part in label_parts: part = part.strip() @@ -290,10 +290,16 @@ def _update_label(self): icon = re.sub(r"|", "", part).strip() active_widgets[widget_index].setText(icon) else: - formatted_text = part.format(info=info) if info else part - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) + + if not active_widgets[widget_index].isVisible(): + active_widgets[widget_index].setVisible(True) + widget_index += 1 + for i in range(widget_index, len(active_widgets)): + active_widgets[i].setVisible(False) + # Update popup menu if it's visible if self._is_menu_visible(): self._update_menu_content() diff --git a/src/core/widgets/yasb/memory.py b/src/core/widgets/yasb/memory.py index a735e185..158454c3 100644 --- a/src/core/widgets/yasb/memory.py +++ b/src/core/widgets/yasb/memory.py @@ -123,25 +123,10 @@ def _update_label(self, virtual_mem, swap_mem): """Update label using shared memory data.""" active_widgets = self._widgets_alt if self._show_alt_label else self._widgets - active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 _round = lambda value: round(value) if self._hide_decimal else value _naturalsize = lambda value: naturalsize(value, True, True, "%.0f" if self._hide_decimal else "%.1f") - label_options = { - "{virtual_mem_free}": _naturalsize(virtual_mem.free), - "{virtual_mem_percent}": _round(virtual_mem.percent), - "{virtual_mem_total}": _naturalsize(virtual_mem.total), - "{virtual_mem_avail}": _naturalsize(virtual_mem.available), - "{virtual_mem_used}": _naturalsize(virtual_mem.used), - "{virtual_mem_outof}": f"{_naturalsize(virtual_mem.used)} / {_naturalsize(virtual_mem.total)}", - "{swap_mem_free}": _naturalsize(swap_mem.free), - "{swap_mem_percent}": _round(swap_mem.percent), - "{swap_mem_total}": _naturalsize(swap_mem.total), - "{histogram}": "".join([self._get_histogram_bar(virtual_mem.percent, 0, 100)]), - } if self._progress_bar["enabled"] and self.progress_widget: if self._widget_container_layout.indexOf(self.progress_widget) == -1: @@ -151,10 +136,25 @@ def _update_label(self, virtual_mem, swap_mem): ) self.progress_widget.set_value(virtual_mem.percent) + active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format( + virtual_mem_free=_naturalsize(virtual_mem.free), + virtual_mem_percent=_round(virtual_mem.percent), + virtual_mem_total=_naturalsize(virtual_mem.total), + virtual_mem_avail=_naturalsize(virtual_mem.available), + virtual_mem_used=_naturalsize(virtual_mem.used), + virtual_mem_outof=f"{_naturalsize(virtual_mem.used)} / {_naturalsize(virtual_mem.total)}", + swap_mem_free=_naturalsize(swap_mem.free), + swap_mem_percent=_round(swap_mem.percent), + swap_mem_total=_naturalsize(swap_mem.total), + histogram="".join([self._get_histogram_bar(virtual_mem.percent, 0, 100)]), + ) + label_parts = re.split("(.*?)", active_label_content) + + virtual_memory_threshold_class = self._get_virtual_memory_threshold(virtual_mem.percent) + for part in label_parts: part = part.strip() - for fmt_str, value in label_options.items(): - part = part.replace(fmt_str, str(value)) if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): if "" in part: @@ -165,7 +165,7 @@ def _update_label(self, virtual_mem, swap_mem): # Set memory threshold as property label_class = "label alt" if self._show_alt_label else "label" active_widgets[widget_index].setProperty( - "class", f"{label_class} status-{self._get_virtual_memory_threshold(virtual_mem.percent)}" + "class", f"{label_class} status-{virtual_memory_threshold_class}" ) refresh_widget_style(active_widgets[widget_index]) widget_index += 1 diff --git a/src/core/widgets/yasb/microphone.py b/src/core/widgets/yasb/microphone.py index 18f0a760..f30a30c1 100644 --- a/src/core/widgets/yasb/microphone.py +++ b/src/core/widgets/yasb/microphone.py @@ -117,8 +117,6 @@ def _toggle_label(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 # Handle no device case @@ -129,15 +127,13 @@ def _update_label(self): else: try: mute_status = self.audio_endpoint.GetMute() - mic_level = round(self.audio_endpoint.GetMasterVolumeLevelScalar() * 100) + mic_level = self.audio_endpoint.GetMasterVolumeLevelScalar() min_icon = self._get_mic_icon() - min_level = self._mute_text if mute_status == 1 else f"{mic_level}%" + min_level = self._mute_text if mute_status == 1 else f"{mic_level:.0%}%" except Exception as e: logging.error(f"Failed to get microphone info: {e}") return - label_options = {"{icon}": min_icon, "{level}": min_level} - if self._progress_bar["enabled"] and self.progress_widget: if self._widget_container_layout.indexOf(self.progress_widget) == -1: self._widget_container_layout.insertWidget( @@ -147,24 +143,20 @@ def _update_label(self): numeric_value = int(re.search(r"\d+", min_level).group()) if re.search(r"\d+", min_level) else 0 self.progress_widget.set_value(numeric_value) + active_label_content = active_label_content.format(icon=min_icon, level=min_level) + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) - self._set_muted_class( - active_widgets[widget_index], mute_status == 1 if mute_status is not None else False - ) + active_widgets[widget_index].setText(part) + self._set_muted_class(active_widgets[widget_index], mute_status == 1) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) - self._set_muted_class( - active_widgets[widget_index], mute_status == 1 if mute_status is not None else False - ) + active_widgets[widget_index].setText(part) + self._set_muted_class(active_widgets[widget_index], mute_status == 1) widget_index += 1 def _update_slider_value(self): diff --git a/src/core/widgets/yasb/notes.py b/src/core/widgets/yasb/notes.py index e8dcd68d..fcae9747 100644 --- a/src/core/widgets/yasb/notes.py +++ b/src/core/widgets/yasb/notes.py @@ -130,13 +130,15 @@ def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] - notes_count = len(self._notes) - for widget_index, part in enumerate(label_parts): - if widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): + active_label_content = active_label_content.format(count=notes_count) + label_parts = re.split("(.*?)", active_label_content) + widget_index = 0 + + for part in label_parts: + part = part.strip() + if not part or widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): continue current_widget = active_widgets[widget_index] @@ -145,8 +147,7 @@ def _update_label(self): icon = re.sub(r"|", "", part).strip() current_widget.setText(icon) else: - formatted_text = part.format(count=notes_count) - current_widget.setText(formatted_text) + current_widget.setText(part) widget_index += 1 def _show_menu(self): diff --git a/src/core/widgets/yasb/notifications.py b/src/core/widgets/yasb/notifications.py index d374e54a..e78b26c1 100644 --- a/src/core/widgets/yasb/notifications.py +++ b/src/core/widgets/yasb/notifications.py @@ -128,17 +128,14 @@ def _update_label(self): else: icon = self._icons["default"] + active_label_content = active_label_content.format(count=self._notification_count, icon=icon) label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 # Provide replacements for {count} and {icon} - label_options = [("{count}", self._notification_count), ("{icon}", icon)] for part in label_parts: part = part.strip() - for option, value in label_options: - part = part.replace(option, str(value)) if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): if "" in part: diff --git a/src/core/widgets/yasb/pomodoro.py b/src/core/widgets/yasb/pomodoro.py index a0beea15..513f4e46 100644 --- a/src/core/widgets/yasb/pomodoro.py +++ b/src/core/widgets/yasb/pomodoro.py @@ -197,22 +197,12 @@ def _toggle_label(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 remaining_str = self._format_time(self._remaining_time) status = "Paused" if self._is_paused else "Break" if self._is_break else "Work" class_name = "paused" if self._is_paused else "break" if self._is_break else "work" - label_options = { - "{remaining}": remaining_str, - "{status}": status, - "{session}": str(self._session_count + 1), - "{total_sessions}": str(self._session_target) if self._session_target > 0 else "∞", - "{icon}": self._get_current_icon(), - } - if self._progress_bar["enabled"] and self.progress_widget: if self._widget_container_layout.indexOf(self.progress_widget) == -1: self._widget_container_layout.insertWidget( @@ -229,22 +219,29 @@ def _update_label(self): percent = (elapsed / max_value) * 100 if max_value > 0 else 0 self.progress_widget.set_value(percent) + active_label_content = active_label_content.format( + remaining=remaining_str, + status=status, + session=str(self._session_count + 1), + total_sessions=str(self._session_target) if self._session_target > 0 else "∞", + icon=self._get_current_icon(), + ) + + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) base_class = active_widgets[widget_index].property("class").split()[0] active_widgets[widget_index].setProperty("class", f"{base_class} {class_name}") refresh_widget_style(active_widgets[widget_index]) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): alt_class = "alt" if self._show_alt_label else "" - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) base_class = "label" active_widgets[widget_index].setProperty("class", f"{base_class} {alt_class} {class_name}") refresh_widget_style(active_widgets[widget_index]) diff --git a/src/core/widgets/yasb/power_plan.py b/src/core/widgets/yasb/power_plan.py index 7be6871e..950add8f 100644 --- a/src/core/widgets/yasb/power_plan.py +++ b/src/core/widgets/yasb/power_plan.py @@ -136,20 +136,16 @@ def _update_label(self): """Update the label with the current power plan name.""" active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 - label_options = {"{active_plan}": self._active_plan_name} + active_label_content = active_label_content.format(active_plan=self._active_plan_name) + label_parts = re.split("(.*?)", active_label_content) for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) # Get the base class (without any power plan classes) alt_class = "alt" if self._show_alt_label else "" base_class = "icon" if ".*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 class_name = "bin-filled" if self._bin_info["num_items"] > 0 else "bin-empty" - label_options = { - "{items_count}": self._bin_info["num_items"], - "{items_size}": naturalsize(self._bin_info["size_bytes"], binary=True, format="%.2f"), - "{icon}": self._get_current_icon(), - } + active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format( + items_count=self._bin_info["num_items"], + items_size=naturalsize(self._bin_info["size_bytes"], binary=True, format="%.2f"), + icon=self._get_current_icon(), + ) + + label_parts = re.split("(.*?)", active_label_content) + label_parts = [part for part in label_parts if part] for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: + part = re.sub(r"|", "", part) if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) base_class = active_widgets[widget_index].property("class").split()[0] active_widgets[widget_index].setProperty("class", f"{base_class} {class_name}") refresh_widget_style(active_widgets[widget_index]) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): alt_class = "alt" if self._show_alt_label else "" - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) base_class = "label" active_widgets[widget_index].setProperty("class", f"{base_class} {alt_class} {class_name}") refresh_widget_style(active_widgets[widget_index]) widget_index += 1 + if self._tooltip: set_tooltip( self._widget_container, diff --git a/src/core/widgets/yasb/server_monitor.py b/src/core/widgets/yasb/server_monitor.py index 134c452a..eef9f7c2 100644 --- a/src/core/widgets/yasb/server_monitor.py +++ b/src/core/widgets/yasb/server_monitor.py @@ -283,8 +283,6 @@ def _toggle_menu(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 try: @@ -307,6 +305,11 @@ def _update_label(self): # Force style update self._widget_container.setStyleSheet(self._widget_container.styleSheet()) + active_label_content = active_label_content.format( + online=online_count, offline=offline_count, total=total_count + ) + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): @@ -315,8 +318,7 @@ def _update_label(self): icon = re.sub(r"|", "", part).strip() active_widgets[widget_index].setText(icon) else: - formatted_text = part.format(online=online_count, offline=offline_count, total=total_count) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 if self._tooltip: set_tooltip( diff --git a/src/core/widgets/yasb/todo.py b/src/core/widgets/yasb/todo.py index f7912458..1c544417 100644 --- a/src/core/widgets/yasb/todo.py +++ b/src/core/widgets/yasb/todo.py @@ -278,15 +278,19 @@ def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] - active_tasks = self._get_filtered_tasks(completed=False) completed_tasks = self._get_filtered_tasks(completed=True) total_tasks = len(self._tasks) active_count = len(active_tasks) completed_count = len(completed_tasks) + active_label_content = active_label_content.format( + count=active_count, total=total_tasks, completed=completed_count + ) + + label_parts = re.split("(.*?)", active_label_content) + label_parts = [part for part in label_parts if part] + for widget_index, part in enumerate(label_parts): if widget_index >= len(active_widgets) or not isinstance(active_widgets[widget_index], QLabel): continue @@ -297,12 +301,7 @@ def _update_label(self): icon = re.sub(r"|", "", part).strip() current_widget.setText(icon) else: - formatted_text = ( - part.replace("{count}", str(active_count)) - .replace("{total}", str(total_tasks)) - .replace("{completed}", str(completed_count)) - ) - current_widget.setText(formatted_text) + current_widget.setText(part) widget_index += 1 # Tooltip: show number of tasks per category, skip 0s diff --git a/src/core/widgets/yasb/traffic.py b/src/core/widgets/yasb/traffic.py index cb40c15a..57e07878 100644 --- a/src/core/widgets/yasb/traffic.py +++ b/src/core/widgets/yasb/traffic.py @@ -250,26 +250,12 @@ def _update_label_with_data(self, shared_data): """Update label with provided data""" active_widgets = self._widgets_alt if self._show_alt_label else self._widgets # type: ignore active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - + active_label_content = active_label_content.format_map(shared_data) label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 - label_options = [ - ("{upload_speed}", shared_data["upload_speed"]), - ("{download_speed}", shared_data["download_speed"]), - ("{today_uploaded}", shared_data["today_uploaded"]), - ("{today_downloaded}", shared_data["today_downloaded"]), - ("{session_uploaded}", shared_data["session_uploaded"]), - ("{session_downloaded}", shared_data["session_downloaded"]), - ("{alltime_uploaded}", shared_data["alltime_uploaded"]), - ("{alltime_downloaded}", shared_data["alltime_downloaded"]), - ] - for part in label_parts: part = part.strip() - for option, value in label_options: - part = part.replace(option, str(value)) if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): if "" in part: diff --git a/src/core/widgets/yasb/update_check.py b/src/core/widgets/yasb/update_check.py index b50bb8e1..c51e0f38 100644 --- a/src/core/widgets/yasb/update_check.py +++ b/src/core/widgets/yasb/update_check.py @@ -372,8 +372,8 @@ def process_content(label_text, label_type): add_shadow(container, self._container_shadow) self.widget_layout.addWidget(container) container.hide() + label_parts = re.split(r"(.*?)", label_text) - label_parts = [part for part in label_parts if part] widgets = [] for part in label_parts: @@ -413,13 +413,16 @@ def _update_label(self, widget_type, data, names): else: return - label_parts = re.split(r"(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] - widget_index = 0 if data == 0: container.hide() return + container.show() + + active_label_content = active_label_content.format(count=data) + label_parts = re.split(r"(.*?)", active_label_content) + widget_index = 0 + for part in label_parts: part = part.strip() if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): @@ -427,8 +430,7 @@ def _update_label(self, widget_type, data, names): icon = re.sub(r"|", "", part).strip() active_widgets[widget_index].setText(icon) else: - formatted_text = part.format(count=data) - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) active_widgets[widget_index].setCursor(Qt.CursorShape.PointingHandCursor) widget_index += 1 if widget_type == "windows" and self._windows_update_tooltip: diff --git a/src/core/widgets/yasb/volume.py b/src/core/widgets/yasb/volume.py index b17b5581..c4d4c128 100644 --- a/src/core/widgets/yasb/volume.py +++ b/src/core/widgets/yasb/volume.py @@ -592,8 +592,6 @@ def _toggle_label(self): def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content - label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 if self.volume is None: @@ -610,8 +608,6 @@ def _update_label(self): logging.error(f"Failed to get volume info: {e}") mute_status, icon_volume, level_volume = None, "", "No Device" - label_options = {"{icon}": icon_volume, "{level}": level_volume} - if self._progress_bar["enabled"] and self.progress_widget and self.volume is not None: if self._widget_container_layout.indexOf(self.progress_widget) == -1: self._widget_container_layout.insertWidget( @@ -621,19 +617,19 @@ def _update_label(self): numeric_value = int(re.search(r"\d+", level_volume).group()) if re.search(r"\d+", level_volume) else 0 self.progress_widget.set_value(numeric_value) + active_label_content = active_label_content.format(icon=icon_volume, level=level_volume) + label_parts = re.split("(.*?)", active_label_content) + for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if "" in part: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) self._set_device_state_classes(active_widgets[widget_index], mute_status == 1) else: if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) self._set_device_state_classes(active_widgets[widget_index], mute_status == 1) widget_index += 1 diff --git a/src/core/widgets/yasb/weather.py b/src/core/widgets/yasb/weather.py index c3c41828..f550056f 100644 --- a/src/core/widgets/yasb/weather.py +++ b/src/core/widgets/yasb/weather.py @@ -214,20 +214,20 @@ def handler(event): frame_today.setProperty("class", "weather-card-today") layout_today = QVBoxLayout(frame_today) - today_label0 = QLabel(f"{self._weather_data['{location}']} {self._weather_data['{temp}']}") + today_label0 = QLabel(f"{self._weather_data['location']} {self._weather_data['temp']}") today_label0.setProperty("class", "label location") today_label0.setAlignment(Qt.AlignmentFlag.AlignCenter) today_label1 = QLabel( - f"Feels like {self._weather_data['{feelslike}']} - {self._weather_data['{condition_text}']} - Humidity {self._weather_data['{humidity}']}\nPressure {self._weather_data['{pressure}']} - Visibility {self._weather_data['{vis}']} - Cloud {self._weather_data['{cloud}']}%\nRain chance {self._weather_data['{daily_chance_of_rain}']} - Snow chance {self._weather_data['{daily_chance_of_snow}']}" + f"Feels like {self._weather_data['feelslike']} - {self._weather_data['condition_text']} - Humidity {self._weather_data['humidity']}\nPressure {self._weather_data['pressure']} - Visibility {self._weather_data['vis']} - Cloud {self._weather_data['cloud']}%\nRain chance {self._weather_data['daily_chance_of_rain']} - Snow chance {self._weather_data['daily_chance_of_snow']}" ) today_label1.setProperty("class", "label") today_label1.setAlignment(Qt.AlignmentFlag.AlignCenter) today_label2 = QLabel( - f"{self._weather_data['{alert_title}']}" - f"{'
Alert expires ' + self._weather_data['{alert_end_date}'] if self._weather_data['{alert_end_date}'] else ''}" - f"
{self._weather_data['{alert_desc}']}" + f"{self._weather_data['alert_title']}" + f"{'
Alert expires ' + self._weather_data['alert_end_date'] if self._weather_data['alert_end_date'] else ''}" + f"
{self._weather_data['alert_desc']}" ) today_label2.setProperty("class", "label alert") today_label2.setAlignment(Qt.AlignmentFlag.AlignCenter) @@ -235,7 +235,7 @@ def handler(event): layout_today.addWidget(today_label0) layout_today.addWidget(today_label1) - if self._show_alerts and self._weather_data["{alert_title}"] and self._weather_data["{alert_desc}"]: + if self._show_alerts and self._weather_data["alert_title"] and self._weather_data["alert_desc"]: layout_today.addWidget(today_label2) @pyqtSlot(int) @@ -288,18 +288,18 @@ def switch_hourly_data(day_idx: int): frame_day.setProperty("class", "weather-card-day") if i == 0: name = "Today" - min_temp = self._weather_data["{min_temp}"] - max_temp = self._weather_data["{max_temp}"] + min_temp = self._weather_data["min_temp"] + max_temp = self._weather_data["max_temp"] else: - name = self._weather_data[f"{{day{i}_name}}"] - min_temp = self._weather_data[f"{{day{i}_min_temp}}"] - max_temp = self._weather_data[f"{{day{i}_max_temp}}"] + name = self._weather_data[f"day{i}_name"] + min_temp = self._weather_data[f"day{i}_min_temp"] + max_temp = self._weather_data[f"day{i}_max_temp"] row_day_label = QLabel(f"{name}\nMin: {min_temp}\nMax: {max_temp}", frame_day) row_day_label.setProperty("class", "label") # Create the icon label and pixmap row_day_icon_label = QLabel(frame_day) - icon_url = self._weather_data[f"{{day{i}_icon}}"] + icon_url = self._weather_data[f"day{i}_icon"] icon_data_day = self._icon_fetcher.get_icon(icon_url) if bool(icon_data_day): self._set_pixmap(row_day_icon_label, icon_data_day) @@ -426,17 +426,17 @@ def _update_label(self, update_class: bool = True): active_widgets = self._show_alt_label and self._widgets_alt or self._widgets active_label_content = self._show_alt_label and self._label_alt_content or self._label_content + active_label_content = active_label_content.format_map(self._weather_data) label_parts = re.split(r"(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] if self._tooltip: tooltip = ( - f"{self._weather_data['{location}']}

Temperature
" - f"Min {self._weather_data['{min_temp}']} / Max {self._weather_data['{max_temp}']}" + f"{self._weather_data['location']}

Temperature
" + f"Min {self._weather_data['min_temp']} / Max {self._weather_data['max_temp']}" ) - rain = self._weather_data["{hourly_chance_of_rain}"] - snow = self._weather_data["{hourly_chance_of_snow}"] + rain = self._weather_data["hourly_chance_of_rain"] + snow = self._weather_data["hourly_chance_of_snow"] if rain != "N/A" and snow != "N/A" and (int(rain.rstrip("%")) > 0 or int(snow.rstrip("%")) > 0): precip = [] @@ -453,8 +453,6 @@ def _update_label(self, update_class: bool = True): try: for part in label_parts: part = part.strip() - for option, value in self._weather_data.items(): - part = part.replace(option, str(value)) if not part or widget_index >= len(active_widgets): continue if "" in part: @@ -463,7 +461,7 @@ def _update_label(self, update_class: bool = True): if update_class: # Retrieve current class and append new class based on weather conditions current_class = active_widgets[widget_index].property("class") or "" - append_class_icon = self._weather_data.get("{icon_class}", "") + append_class_icon = self._weather_data.get("icon_class", "") # Create the new class string new_class = f"{current_class} {append_class_icon}" active_widgets[widget_index].setProperty("class", new_class) @@ -531,56 +529,56 @@ def process_weather_data(self, weather_data: dict[str, Any]): self._weather_data = { # Current conditions - "{temp}": self._format_temp(current["temp_f"], current["temp_c"]), - "{feelslike}": self._format_temp(current["feelslike_f"], current["feelslike_c"]), - "{humidity}": f"{current['humidity']}%", - "{cloud}": current["cloud"], + "temp": self._format_temp(current["temp_f"], current["temp_c"]), + "feelslike": self._format_temp(current["feelslike_f"], current["feelslike_c"]), + "humidity": f"{current['humidity']}%", + "cloud": current["cloud"], # Forecast today - "{min_temp}": self._format_temp(forecast["mintemp_f"], forecast["mintemp_c"]), - "{max_temp}": self._format_temp(forecast["maxtemp_f"], forecast["maxtemp_c"]), + "min_temp": self._format_temp(forecast["mintemp_f"], forecast["mintemp_c"]), + "max_temp": self._format_temp(forecast["maxtemp_f"], forecast["maxtemp_c"]), # Rain/Snow chances (daily) - "{daily_chance_of_rain}": f"{forecast.get('daily_chance_of_rain', 0)}%", - "{daily_chance_of_snow}": f"{forecast.get('daily_chance_of_snow', 0)}%", + "daily_chance_of_rain": f"{forecast.get('daily_chance_of_rain', 0)}%", + "daily_chance_of_snow": f"{forecast.get('daily_chance_of_snow', 0)}%", # Rain/Snow chances (hourly) - "{hourly_chance_of_rain}": f"{self._hourly_data_today[self._current_time.hour].get('chance_of_rain', 0) if self._hourly_data_today and self._current_time else 0}%", - "{hourly_chance_of_snow}": f"{self._hourly_data_today[self._current_time.hour].get('chance_of_snow', 0) if self._hourly_data_today and self._current_time else 0}%", + "hourly_chance_of_rain": f"{self._hourly_data_today[self._current_time.hour].get('chance_of_rain', 0) if self._hourly_data_today and self._current_time else 0}%", + "hourly_chance_of_snow": f"{self._hourly_data_today[self._current_time.hour].get('chance_of_snow', 0) if self._hourly_data_today and self._current_time else 0}%", # Location and conditions - "{location}": weather_data["location"]["name"], - "{location_region}": weather_data["location"]["region"], - "{location_country}": weather_data["location"]["country"], - "{time_zone}": weather_data["location"]["tz_id"], - "{localtime}": weather_data["location"]["localtime"], - "{conditions}": conditions_data, - "{condition_text}": weather_text, - "{is_day}": "Day" if current["is_day"] else "Night", + "location": weather_data["location"]["name"], + "location_region": weather_data["location"]["region"], + "location_country": weather_data["location"]["country"], + "time_zone": weather_data["location"]["tz_id"], + "localtime": weather_data["location"]["localtime"], + "conditions": conditions_data, + "condition_text": weather_text, + "is_day": "Day" if current["is_day"] else "Night", # Icons - "{icon}": weather_icon_string, - "{icon_class}": weather_icon_string, - "{day0_icon}": f"http:{forecast['condition']['icon']}", + "icon": weather_icon_string, + "icon_class": weather_icon_string, + "day0_icon": f"http:{forecast['condition']['icon']}", # Wind data - "{wind}": self._format_measurement(current["wind_mph"], "mph", current["wind_kph"], "km/h"), - "{wind_dir}": current["wind_dir"], - "{wind_degree}": current["wind_degree"], + "wind": self._format_measurement(current["wind_mph"], "mph", current["wind_kph"], "km/h"), + "wind_dir": current["wind_dir"], + "wind_degree": current["wind_degree"], # Other measurements - "{pressure}": self._format_measurement(current["pressure_in"], "in", current["pressure_mb"], "mb"), - "{precip}": self._format_measurement(current["precip_in"], "in", current["precip_mm"], "mm"), - "{vis}": self._format_measurement(current["vis_miles"], "mi", current["vis_km"], "km"), - "{uv}": current["uv"], + "pressure": self._format_measurement(current["pressure_in"], "in", current["pressure_mb"], "mb"), + "precip": self._format_measurement(current["precip_in"], "in", current["precip_mm"], "mm"), + "vis": self._format_measurement(current["vis_miles"], "mi", current["vis_km"], "km"), + "uv": current["uv"], # Future forecasts - "{day1_name}": self._format_date_string(forecast1["date"]), - "{day1_min_temp}": self._format_temp(forecast1["day"]["mintemp_f"], forecast1["day"]["mintemp_c"]), - "{day1_max_temp}": self._format_temp(forecast1["day"]["maxtemp_f"], forecast1["day"]["maxtemp_c"]), - "{day1_icon}": f"http:{forecast1['day']['condition']['icon']}", - "{day2_name}": self._format_date_string(forecast2["date"]), - "{day2_min_temp}": self._format_temp(forecast2["day"]["mintemp_f"], forecast2["day"]["mintemp_c"]), - "{day2_max_temp}": self._format_temp(forecast2["day"]["maxtemp_f"], forecast2["day"]["maxtemp_c"]), - "{day2_icon}": f"http:{forecast2['day']['condition']['icon']}", + "day1_name": self._format_date_string(forecast1["date"]), + "day1_min_temp": self._format_temp(forecast1["day"]["mintemp_f"], forecast1["day"]["mintemp_c"]), + "day1_max_temp": self._format_temp(forecast1["day"]["maxtemp_f"], forecast1["day"]["maxtemp_c"]), + "day1_icon": f"http:{forecast1['day']['condition']['icon']}", + "day2_name": self._format_date_string(forecast2["date"]), + "day2_min_temp": self._format_temp(forecast2["day"]["mintemp_f"], forecast2["day"]["mintemp_c"]), + "day2_max_temp": self._format_temp(forecast2["day"]["maxtemp_f"], forecast2["day"]["maxtemp_c"]), + "day2_icon": f"http:{forecast2['day']['condition']['icon']}", # Alerts - "{alert_title}": alerts["alert"][0]["headline"] + "alert_title": alerts["alert"][0]["headline"] if alerts["alert"] and alerts["alert"][0]["headline"] else None, - "{alert_desc}": alerts["alert"][0]["desc"] if alerts["alert"] and alerts["alert"][0]["desc"] else None, - "{alert_end_date}": self._format_alert_datetime(alerts["alert"][0]["expires"]) + "alert_desc": alerts["alert"][0]["desc"] if alerts["alert"] and alerts["alert"][0]["desc"] else None, + "alert_end_date": self._format_alert_datetime(alerts["alert"][0]["expires"]) if alerts["alert"] and alerts["alert"][0]["expires"] else None, } @@ -593,45 +591,45 @@ def process_weather_data(self, weather_data: dict[str, Any]): self._retry_timer.start(10000) if self._weather_data is None: self._weather_data = { - "{temp}": "N/A", - "{min_temp}": "N/A", - "{max_temp}": "N/A", - "{daily_chance_of_rain}": "N/A", - "{daily_chance_of_snow}": "N/A", - "{hourly_chance_of_rain}": "N/A", - "{hourly_chance_of_snow}": "N/A", - "{location}": "N/A", - "{location_region}": "N/A", - "{location_country}": "N/A", - "{time_zone}": "N/A", - "{localtime}": "N/A", - "{humidity}": "N/A", - "{is_day}": "N/A", - "{day0_icon}": "N/A", - "{icon}": "N/A", - "{icon_class}": "N/A", - "{conditions}": "N/A", - "{condition_text}": "N/A", - "{wind}": "N/A", - "{wind_dir}": "N/A", - "{wind_degree}": "N/A", - "{pressure}": "N/A", - "{precip}": "N/A", - "{uv}": "N/A", - "{vis}": "N/A", - "{cloud}": "N/A", - "{feelslike}": "N/A", - "{day1_name}": "N/A", - "{day1_min_temp}": "N/A", - "{day1_max_temp}": "N/A", - "{day1_icon}": "N/A", - "{day2_name}": "N/A", - "{day2_min_temp}": "N/A", - "{day2_max_temp}": "N/A", - "{day2_icon}": "N/A", - "{alert_title}": None, - "{alert_desc}": None, - "{alert_end_date}": None, + "temp": "N/A", + "min_temp": "N/A", + "max_temp": "N/A", + "daily_chance_of_rain": "N/A", + "daily_chance_of_snow": "N/A", + "hourly_chance_of_rain": "N/A", + "hourly_chance_of_snow": "N/A", + "location": "N/A", + "location_region": "N/A", + "location_country": "N/A", + "time_zone": "N/A", + "localtime": "N/A", + "humidity": "N/A", + "is_day": "N/A", + "day0_icon": "N/A", + "icon": "N/A", + "icon_class": "N/A", + "conditions": "N/A", + "condition_text": "N/A", + "wind": "N/A", + "wind_dir": "N/A", + "wind_degree": "N/A", + "pressure": "N/A", + "precip": "N/A", + "uv": "N/A", + "vis": "N/A", + "cloud": "N/A", + "feelslike": "N/A", + "day1_name": "N/A", + "day1_min_temp": "N/A", + "day1_max_temp": "N/A", + "day1_icon": "N/A", + "day2_name": "N/A", + "day2_min_temp": "N/A", + "day2_max_temp": "N/A", + "day2_icon": "N/A", + "alert_title": None, + "alert_desc": None, + "alert_end_date": None, } diff --git a/src/core/widgets/yasb/wifi.py b/src/core/widgets/yasb/wifi.py index de6d1e66..5f61b55e 100644 --- a/src/core/widgets/yasb/wifi.py +++ b/src/core/widgets/yasb/wifi.py @@ -204,23 +204,17 @@ def _update_label(self): active_widgets = self._widgets_alt if self._show_alt_label else self._widgets active_label_content = self._label_alt_content if self._show_alt_label else self._label_content + active_label_content = active_label_content.format( + wifi_icon=wifi_icon, wifi_name=wifi_name, wifi_strength=wifi_strength, ip_addr=ip_addr + ) label_parts = re.split("(.*?)", active_label_content) - label_parts = [part for part in label_parts if part] widget_index = 0 - label_options = { - "{wifi_icon}": wifi_icon, - "{wifi_name}": wifi_name, - "{wifi_strength}": wifi_strength, - "{ip_addr}": ip_addr, - } + for part in label_parts: part = part.strip() if part: - formatted_text = part - for option, value in label_options.items(): - formatted_text = formatted_text.replace(option, str(value)) if widget_index < len(active_widgets): - active_widgets[widget_index].setText(formatted_text) + active_widgets[widget_index].setText(part) widget_index += 1 def _get_wifi_strength_safe(self) -> int: