✨ feat(controlcenter): redesign battery widget with energy modes and game mode toggles
This commit is contained in:
1 parent
1e456b7fd0
commit
a07b556438
2 files changed
+314
-397
No files matched your search
+269
-279
@@ -1,387 +1,377 @@
|
||||
from fabric.utils import get_relative_path
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.svg import Svg
|
||||
from fabric.widgets.image import Image
|
||||
from fabric.widgets.separator import Separator
|
||||
from services.battery import Battery
|
||||
import subprocess
|
||||
from fabric.utils import get_relative_path
|
||||
import os
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
class PowerProfileButton(Button):
|
||||
def __init__(self, profile_name: str, display_name: str, battery_service: Battery, parent, **kwargs):
|
||||
class EnergyModeButton(CenterBox):
|
||||
def __init__(
|
||||
self,
|
||||
profile_name: str,
|
||||
display_name: str,
|
||||
icon_name: str,
|
||||
battery_service: Battery,
|
||||
parent,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(name="energy-mode-button", **kwargs)
|
||||
self.profile_name = profile_name
|
||||
self.battery_service = battery_service
|
||||
self.parent = parent
|
||||
|
||||
# Get symbolic icon for profile
|
||||
profile_icons = {
|
||||
"power-saver": "power-profile-power-saver-symbolic",
|
||||
"powersave": "power-profile-power-saver-symbolic",
|
||||
"power_saver": "power-profile-power-saver-symbolic",
|
||||
"balanced": "power-profile-balanced-symbolic",
|
||||
"balance": "power-profile-balanced-symbolic",
|
||||
"performance": "power-profile-performance-symbolic",
|
||||
"performance-mode": "power-profile-performance-symbolic"
|
||||
}
|
||||
|
||||
icon_name = profile_icons.get(profile_name, "preferences-system-symbolic")
|
||||
|
||||
# Create symbolic icon
|
||||
from fabric.widgets.image import Image
|
||||
self.profile_icon = Image(
|
||||
icon_name=icon_name,
|
||||
size=20,
|
||||
style_classes="battery-profile-icon"
|
||||
self.mode_icon = Image(
|
||||
icon_name=f"battery-{icon_name}-symbolic",
|
||||
size=16,
|
||||
name="energy-mode-icon",
|
||||
style_classes="battery-profile-icon",
|
||||
)
|
||||
|
||||
self.profile_label = Label(
|
||||
self.mode_label = Label(
|
||||
label=display_name,
|
||||
style_classes="battery-profile-label"
|
||||
style_classes="battery-power-source",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
)
|
||||
|
||||
# Create vertical layout for icon and label
|
||||
content = Box(
|
||||
orientation="vertical",
|
||||
spacing=2,
|
||||
children=[self.profile_icon, self.profile_label],
|
||||
h_align="center"
|
||||
start_box = Box(
|
||||
orientation="horizontal",
|
||||
spacing=8,
|
||||
children=[self.mode_icon, self.mode_label],
|
||||
)
|
||||
|
||||
super().__init__(
|
||||
child=content,
|
||||
|
||||
self.button = Button(
|
||||
child=start_box,
|
||||
name="energy-mode-button-clickable",
|
||||
on_clicked=self.on_clicked,
|
||||
style_classes="battery-profile-button",
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# Update initial state
|
||||
|
||||
self.start_children = [self.button]
|
||||
self.update_state()
|
||||
|
||||
|
||||
def on_clicked(self, *args):
|
||||
"""Handle profile selection"""
|
||||
success = self.battery_service.change_power_profile(self.profile_name)
|
||||
if success:
|
||||
# Update all profile buttons in parent
|
||||
self.parent.update_profile_buttons()
|
||||
|
||||
self.parent.update_energy_mode_buttons()
|
||||
|
||||
# Reset icon state after short delay
|
||||
GLib.timeout_add(300, lambda: self._reset_icon_state())
|
||||
|
||||
def _reset_icon_state(self):
|
||||
return False # Remove timeout
|
||||
|
||||
def update_state(self):
|
||||
"""Update the visual state based on current active profile"""
|
||||
is_active = self.battery_service.power_profile == self.profile_name
|
||||
|
||||
if is_active:
|
||||
self.add_style_class("active")
|
||||
self.mode_icon.add_style_class("connected")
|
||||
else:
|
||||
self.remove_style_class("active")
|
||||
self.mode_icon.remove_style_class("connected")
|
||||
|
||||
|
||||
class GameModeButton(Button):
|
||||
def __init__(self, **kwargs):
|
||||
self.script_path = get_relative_path("../../scripts/gamemode.sh")
|
||||
self.gamemode_active = self.check_gamemode_status()
|
||||
class GameModeButton(CenterBox):
|
||||
def __init__(self, parent, **kwargs):
|
||||
super().__init__(name="game-mode-button", **kwargs)
|
||||
self.parent = parent
|
||||
|
||||
# Create icon for gamemode
|
||||
self.gamemode_icon = Image(
|
||||
icon_name="applications-games-symbolic" if self.gamemode_active else "applications-games-symbolic",
|
||||
size=20,
|
||||
style_classes="battery-gamemode-icon"
|
||||
self.game_icon = Image(
|
||||
icon_name="applications-games-symbolic",
|
||||
size=16,
|
||||
name="game-mode-icon",
|
||||
style_classes="battery-gamemode-icon",
|
||||
)
|
||||
|
||||
self.gamemode_label = Label(
|
||||
self.game_label = Label(
|
||||
label="Game Mode",
|
||||
style_classes="battery-gamemode-label"
|
||||
style_classes="battery-power-source",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
)
|
||||
|
||||
# Create vertical layout for icon and label
|
||||
content = Box(
|
||||
orientation="vertical",
|
||||
spacing=2,
|
||||
children=[self.gamemode_icon, self.gamemode_label],
|
||||
h_align="center"
|
||||
start_box = Box(
|
||||
orientation="horizontal",
|
||||
spacing=8,
|
||||
children=[self.game_icon, self.game_label],
|
||||
)
|
||||
|
||||
super().__init__(
|
||||
child=content,
|
||||
on_clicked=self.toggle_gamemode,
|
||||
self.button = Button(
|
||||
child=start_box,
|
||||
name="game-mode-button-clickable",
|
||||
on_clicked=self.on_clicked,
|
||||
style_classes="battery-gamemode-button",
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# Update initial state
|
||||
self.start_children = [self.button]
|
||||
self.update_state()
|
||||
|
||||
def check_gamemode_status(self):
|
||||
"""Check if gamemode is currently active"""
|
||||
def on_clicked(self, *args):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.script_path, "check"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5
|
||||
)
|
||||
return result.stdout.strip() == "t"
|
||||
except Exception:
|
||||
return False
|
||||
script_path = get_relative_path("../../scripts/gamemode.sh")
|
||||
subprocess.run([script_path], check=False)
|
||||
|
||||
def toggle_gamemode(self, *args):
|
||||
"""Toggle gamemode state"""
|
||||
try:
|
||||
# Make script executable if it isn't
|
||||
os.chmod(self.script_path, 0o755)
|
||||
|
||||
# Run the toggle script
|
||||
subprocess.run([self.script_path], timeout=10)
|
||||
|
||||
# Update state after toggle
|
||||
self.gamemode_active = self.check_gamemode_status()
|
||||
self.update_state()
|
||||
GLib.timeout_add(500, lambda: self.update_state())
|
||||
except Exception as e:
|
||||
print(f"Failed to toggle gamemode: {e}")
|
||||
print(f"Failed to toggle game mode: {e}")
|
||||
|
||||
GLib.timeout_add(300, lambda: self._reset_icon_state())
|
||||
|
||||
def _reset_icon_state(self):
|
||||
return False # Remove timeout
|
||||
|
||||
def update_state(self):
|
||||
"""Update the visual state based on gamemode status"""
|
||||
if self.gamemode_active:
|
||||
self.add_style_class("active")
|
||||
self.gamemode_icon.set_property("style-classes", "battery-gamemode-icon active")
|
||||
else:
|
||||
self.remove_style_class("active")
|
||||
self.gamemode_icon.set_property("style-classes", "battery-gamemode-icon")
|
||||
try:
|
||||
script_path = get_relative_path("../../scripts/gamemode.sh")
|
||||
result = subprocess.run(
|
||||
[script_path, "check"], capture_output=True, text=True, check=False
|
||||
)
|
||||
is_active = result.stdout.strip() == "t"
|
||||
|
||||
if is_active:
|
||||
self.game_icon.add_style_class("connected")
|
||||
else:
|
||||
self.game_icon.remove_style_class("connected")
|
||||
except Exception as e:
|
||||
print(f"Failed to check game mode status: {e}")
|
||||
# Default to inactive state on error
|
||||
self.game_icon.remove_style_class("connected")
|
||||
|
||||
return False # Remove timeout if called from GLib.timeout_add
|
||||
|
||||
|
||||
class BatteryControl(Box):
|
||||
def __init__(self, parent, **kwargs):
|
||||
super().__init__(
|
||||
spacing=0,
|
||||
spacing=12,
|
||||
orientation="vertical",
|
||||
name="control-center-widgets",
|
||||
**kwargs,
|
||||
)
|
||||
self.set_size_request(300, -1)
|
||||
self.set_size_request(400, -1)
|
||||
|
||||
self.parent = parent
|
||||
self.battery_service = Battery()
|
||||
self.profile_buttons = []
|
||||
self.energy_mode_buttons = []
|
||||
|
||||
# Battery information widget in control center style
|
||||
self.battery_info_widget = Box(
|
||||
name="battery-info-widget",
|
||||
self.battery_widget = Box(
|
||||
name="battery-widget",
|
||||
orientation="vertical",
|
||||
style_classes="menu",
|
||||
style_classes="battery-status-section",
|
||||
h_expand=True,
|
||||
children=[
|
||||
Label(label="Battery", style_classes="title", h_align="start"),
|
||||
]
|
||||
)
|
||||
|
||||
# Battery status labels
|
||||
self.battery_percentage = Label(
|
||||
label="100%",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start"
|
||||
)
|
||||
|
||||
self.battery_state = Label(
|
||||
label="Fully Charged",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start"
|
||||
)
|
||||
|
||||
self.battery_capacity = Label(
|
||||
label="",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start"
|
||||
)
|
||||
|
||||
self.battery_time_to_full = Label(
|
||||
label="",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start",
|
||||
visible=False
|
||||
)
|
||||
|
||||
self.battery_time_to_empty = Label(
|
||||
label="",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start",
|
||||
visible=False
|
||||
)
|
||||
|
||||
self.battery_temperature = Label(
|
||||
label="",
|
||||
style_classes="battery-info-item",
|
||||
h_align="start"
|
||||
)
|
||||
|
||||
# Add battery info to widget
|
||||
self.battery_info_widget.add(self.battery_percentage)
|
||||
self.battery_info_widget.add(self.battery_state)
|
||||
self.battery_info_widget.add(self.battery_capacity)
|
||||
self.battery_info_widget.add(self.battery_time_to_full)
|
||||
self.battery_info_widget.add(self.battery_time_to_empty)
|
||||
self.battery_info_widget.add(self.battery_temperature)
|
||||
|
||||
# Power profiles widget in control center style
|
||||
self.profiles_widget = Box(
|
||||
name="power-profiles-widget",
|
||||
orientation="vertical",
|
||||
style_classes="menu",
|
||||
h_expand=True,
|
||||
children=[
|
||||
Label(label="Power Profiles", style_classes="title", h_align="start"),
|
||||
]
|
||||
)
|
||||
|
||||
# Power profiles container
|
||||
self.profiles_container = Box(
|
||||
orientation="horizontal",
|
||||
spacing=8,
|
||||
style_classes="battery-profiles-container",
|
||||
h_align="center"
|
||||
)
|
||||
|
||||
self.profiles_widget.add(self.profiles_container)
|
||||
|
||||
# Game mode widget in control center style
|
||||
self.gamemode_widget = Box(
|
||||
name="gamemode-widget",
|
||||
orientation="vertical",
|
||||
style_classes="menu",
|
||||
h_expand=True,
|
||||
children=[
|
||||
Label(label="Game Mode", style_classes="title", h_align="start"),
|
||||
]
|
||||
self.battery_title = Label(
|
||||
label="Battery", style_classes="battery-main-title", h_align="start"
|
||||
)
|
||||
|
||||
# Add gamemode button
|
||||
self.gamemode_button = GameModeButton()
|
||||
gamemode_container = Box(
|
||||
orientation="horizontal",
|
||||
spacing=8,
|
||||
style_classes="battery-gamemode-container",
|
||||
h_align="center",
|
||||
children=[self.gamemode_button]
|
||||
self.battery_percentage_label = Label(
|
||||
label="80%", style_classes="battery-percentage", h_align="end"
|
||||
)
|
||||
self.gamemode_widget.add(gamemode_container)
|
||||
|
||||
# Add all widgets to main container
|
||||
self.add(self.battery_info_widget)
|
||||
self.add(self.profiles_widget)
|
||||
self.add(self.gamemode_widget)
|
||||
self.battery_header = CenterBox(
|
||||
start_children=self.battery_title,
|
||||
end_children=self.battery_percentage_label,
|
||||
name="battery-header",
|
||||
)
|
||||
|
||||
self.power_source_label = Label(
|
||||
label="Power Source: Power Adapter",
|
||||
style_classes="battery-power-source",
|
||||
h_align="start",
|
||||
)
|
||||
|
||||
self.charging_time_label = Label(
|
||||
label="1h 4m until fully charged",
|
||||
style_classes="battery-power-source",
|
||||
h_align="start",
|
||||
)
|
||||
|
||||
self.energy_mode_section = Box(
|
||||
orientation="vertical", spacing=8, name="energy-mode-section"
|
||||
)
|
||||
|
||||
self.energy_mode_title = Label(
|
||||
label="Energy Mode", style_classes="battery-section-title", h_align="start"
|
||||
)
|
||||
|
||||
self.energy_modes_container = Box(
|
||||
orientation="vertical", spacing=4, name="energy-modes-container"
|
||||
)
|
||||
|
||||
self.game_mode_section = Box(
|
||||
orientation="vertical", spacing=8, name="game-mode-section"
|
||||
)
|
||||
|
||||
self.game_mode_title = Label(
|
||||
label="Game Mode", style_classes="battery-section-title", h_align="start"
|
||||
)
|
||||
|
||||
self.game_mode_container = Box(
|
||||
orientation="vertical", spacing=4, name="game-mode-container"
|
||||
)
|
||||
|
||||
self.battery_settings_button = Button(
|
||||
child=Label(
|
||||
label="Battery Settings...",
|
||||
style_classes="battery-power-source",
|
||||
h_align="start",
|
||||
),
|
||||
style_classes="battery-settings-button",
|
||||
on_clicked=self.open_battery_settings,
|
||||
)
|
||||
|
||||
self.battery_widget.add(self.battery_header)
|
||||
self.battery_widget.add(self.power_source_label)
|
||||
self.battery_widget.add(self.charging_time_label)
|
||||
|
||||
separator1 = Separator(orientation="h", name="separator")
|
||||
self.battery_widget.add(separator1)
|
||||
|
||||
self.energy_mode_section.add(self.energy_mode_title)
|
||||
self.energy_mode_section.add(self.energy_modes_container)
|
||||
self.battery_widget.add(self.energy_mode_section)
|
||||
|
||||
separator2 = Separator(orientation="h", name="separator")
|
||||
self.battery_widget.add(separator2)
|
||||
|
||||
self.game_mode_section.add(self.game_mode_title)
|
||||
self.game_mode_section.add(self.game_mode_container)
|
||||
self.battery_widget.add(self.game_mode_section)
|
||||
|
||||
separator3 = Separator(orientation="h", name="separator")
|
||||
self.battery_widget.add(separator3)
|
||||
|
||||
self.battery_widget.add(self.battery_settings_button)
|
||||
|
||||
self.add(self.battery_widget)
|
||||
|
||||
# Connect to battery service signals
|
||||
self.battery_service.connect("changed", self.on_battery_changed)
|
||||
self.battery_service.connect("profile_changed", self.on_profile_changed)
|
||||
|
||||
# Initialize display
|
||||
self.update_battery_info()
|
||||
self.create_profile_buttons()
|
||||
|
||||
self.create_energy_mode_buttons()
|
||||
self.create_game_mode_button()
|
||||
|
||||
|
||||
def create_profile_buttons(self):
|
||||
"""Create buttons for available power profiles"""
|
||||
def open_battery_settings(self, *args):
|
||||
# TODO: Implement to open Battery Settings
|
||||
pass
|
||||
|
||||
def create_energy_mode_buttons(self):
|
||||
# Clear existing buttons
|
||||
for button in self.profile_buttons:
|
||||
for button in self.energy_mode_buttons:
|
||||
button.destroy()
|
||||
self.profile_buttons.clear()
|
||||
|
||||
self.energy_mode_buttons.clear()
|
||||
|
||||
# Get available profiles
|
||||
available_profiles = self.battery_service.available_profiles
|
||||
|
||||
|
||||
if not available_profiles:
|
||||
no_profiles_label = Label(
|
||||
label="No power profiles available",
|
||||
label="No energy modes available",
|
||||
style_classes="battery-no-profiles",
|
||||
h_align="center"
|
||||
h_align="start",
|
||||
)
|
||||
self.profiles_container.add(no_profiles_label)
|
||||
self.energy_modes_container.add(no_profiles_label)
|
||||
return
|
||||
|
||||
# Create button for each profile
|
||||
|
||||
# Define energy mode mappings with proper icon names
|
||||
energy_mode_config = {
|
||||
"balanced": {"display": "Automatic", "icon": "good"},
|
||||
"power-saver": {"display": "Low Power", "icon": "low"},
|
||||
"powersave": {"display": "Low Power", "icon": "low"},
|
||||
"performance": {"display": "High Power", "icon": "full"},
|
||||
}
|
||||
|
||||
# Define the desired order for energy modes
|
||||
desired_order = ["balanced", "power-saver", "powersave", "performance"]
|
||||
|
||||
# Create ordered list of available profiles
|
||||
ordered_profiles = []
|
||||
for profile_name in desired_order:
|
||||
if profile_name in available_profiles:
|
||||
ordered_profiles.append(profile_name)
|
||||
|
||||
# Add any remaining profiles not in the desired order
|
||||
for profile in available_profiles:
|
||||
display_name = Battery.get_profile_display_name(profile)
|
||||
button = PowerProfileButton(
|
||||
profile_name=profile,
|
||||
display_name=display_name,
|
||||
battery_service=self.battery_service,
|
||||
parent=self
|
||||
if profile not in ordered_profiles:
|
||||
ordered_profiles.append(profile)
|
||||
|
||||
# Create button for each available profile in the specified order
|
||||
for profile in ordered_profiles:
|
||||
config = energy_mode_config.get(
|
||||
profile, {"display": profile.title(), "icon": "good"}
|
||||
)
|
||||
self.profile_buttons.append(button)
|
||||
self.profiles_container.add(button)
|
||||
|
||||
def update_profile_buttons(self):
|
||||
"""Update the state of all profile buttons"""
|
||||
for button in self.profile_buttons:
|
||||
|
||||
button = EnergyModeButton(
|
||||
profile_name=profile,
|
||||
display_name=config["display"],
|
||||
icon_name=config["icon"],
|
||||
battery_service=self.battery_service,
|
||||
parent=self,
|
||||
)
|
||||
self.energy_mode_buttons.append(button)
|
||||
self.energy_modes_container.add(button)
|
||||
|
||||
def update_energy_mode_buttons(self):
|
||||
for button in self.energy_mode_buttons:
|
||||
button.update_state()
|
||||
|
||||
def create_game_mode_button(self):
|
||||
# Clear existing game mode button if any
|
||||
for child in list(self.game_mode_container.get_children()):
|
||||
child.destroy()
|
||||
|
||||
# Create game mode button
|
||||
self.game_mode_button = GameModeButton(parent=self)
|
||||
self.game_mode_container.add(self.game_mode_button)
|
||||
|
||||
def update_battery_info(self):
|
||||
"""Update battery information display"""
|
||||
if not self.battery_service.is_present:
|
||||
self.battery_percentage.set_label("No Battery")
|
||||
self.battery_state.set_label("Not Present")
|
||||
self.battery_capacity.set_label("")
|
||||
self.battery_time_to_full.set_visible(False)
|
||||
self.battery_time_to_empty.set_visible(False)
|
||||
self.battery_temperature.set_label("")
|
||||
self.battery_percentage_label.set_label("No Battery")
|
||||
self.power_source_label.set_label("Power Source: Not Present")
|
||||
self.charging_time_label.set_label("")
|
||||
return
|
||||
|
||||
# Update percentage
|
||||
# Update percentage in header
|
||||
percentage = self.battery_service.percentage
|
||||
self.battery_percentage.set_label(f"Charge: {percentage}%")
|
||||
self.battery_percentage_label.set_label(f"{percentage}%")
|
||||
|
||||
# Update state
|
||||
# Update power source and charging info
|
||||
state = self.battery_service.state
|
||||
state_text = state.replace("_", " ").title()
|
||||
self.battery_state.set_label(f"Status: {state_text}")
|
||||
|
||||
# Update capacity
|
||||
capacity = getattr(self.battery_service, 'capacity', None)
|
||||
if capacity is not None:
|
||||
try:
|
||||
# Try to convert to float if it's a string
|
||||
capacity_value = float(capacity)
|
||||
self.battery_capacity.set_label(f"Capacity: {capacity_value:.1f} Wh")
|
||||
except (ValueError, TypeError):
|
||||
# If conversion fails, display as string
|
||||
self.battery_capacity.set_label(f"Capacity: {capacity}")
|
||||
if state == "CHARGING":
|
||||
self.power_source_label.set_label("Power Source: Power Adapter")
|
||||
time_to_full = self.battery_service.time_to_full
|
||||
if time_to_full != "N/A":
|
||||
self.charging_time_label.set_label(
|
||||
f"{time_to_full} until fully charged"
|
||||
)
|
||||
else:
|
||||
self.charging_time_label.set_label("Charging...")
|
||||
elif state == "FULLY_CHARGED":
|
||||
self.power_source_label.set_label("Power Source: Power Adapter")
|
||||
self.charging_time_label.set_label("Fully Charged")
|
||||
elif state == "DISCHARGING":
|
||||
self.power_source_label.set_label("Power Source: Battery")
|
||||
time_to_empty = self.battery_service.time_to_empty
|
||||
if time_to_empty != "N/A":
|
||||
self.charging_time_label.set_label(f"{time_to_empty} remaining")
|
||||
else:
|
||||
self.charging_time_label.set_label("On Battery Power")
|
||||
else:
|
||||
self.battery_capacity.set_label("Capacity: N/A")
|
||||
|
||||
# Update time to full
|
||||
time_to_full = self.battery_service.time_to_full
|
||||
if time_to_full != "N/A" and state == "CHARGING":
|
||||
self.battery_time_to_full.set_label(f"Time to full: {time_to_full}")
|
||||
self.battery_time_to_full.set_visible(True)
|
||||
else:
|
||||
self.battery_time_to_full.set_visible(False)
|
||||
|
||||
# Update time to empty
|
||||
time_to_empty = self.battery_service.time_to_empty
|
||||
if time_to_empty != "N/A" and state == "DISCHARGING":
|
||||
self.battery_time_to_empty.set_label(f"Time remaining: {time_to_empty}")
|
||||
self.battery_time_to_empty.set_visible(True)
|
||||
else:
|
||||
self.battery_time_to_empty.set_visible(False)
|
||||
|
||||
# Update temperature
|
||||
temperature = getattr(self.battery_service, 'temperature', None)
|
||||
if temperature is not None:
|
||||
try:
|
||||
# Try to convert to float and convert from tenths of degrees Celsius to Celsius
|
||||
temp_value = float(temperature) / 10.0
|
||||
self.battery_temperature.set_label(f"Temperature: {temp_value:.1f}°C")
|
||||
except (ValueError, TypeError):
|
||||
# If conversion fails, display as string
|
||||
self.battery_temperature.set_label(f"Temperature: {temperature}")
|
||||
else:
|
||||
self.battery_temperature.set_label("Temperature: N/A")
|
||||
self.power_source_label.set_label("Power Source: Unknown")
|
||||
self.charging_time_label.set_label("")
|
||||
|
||||
def on_battery_changed(self, *args):
|
||||
"""Handle battery service changes"""
|
||||
self.update_battery_info()
|
||||
|
||||
def on_profile_changed(self, service, new_profile):
|
||||
"""Handle power profile changes"""
|
||||
self.update_profile_buttons()
|
||||
self.update_energy_mode_buttons()
|
||||
+45
-118
@@ -1,20 +1,15 @@
|
||||
.battery-main-title {
|
||||
font-size: 1em;
|
||||
font-weight: 600;
|
||||
font-weight: 900;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
margin: 6px 10px;
|
||||
}
|
||||
|
||||
.battery-power-source {
|
||||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin: 4px 12px;
|
||||
}
|
||||
|
||||
.battery-separator {
|
||||
min-height: 1px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
margin: 4px 0;
|
||||
margin: 0px 12px;
|
||||
}
|
||||
|
||||
.battery-section-title {
|
||||
@@ -29,42 +24,12 @@
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.battery-energy-indicator {
|
||||
font-size: 0.8em;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.battery-energy-app {
|
||||
font-size: 0.9em;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.battery-settings-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 8px 12px;
|
||||
margin: 4px 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.battery-settings-button:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.battery-info-item {
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin: 2px 10px;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
.battery-status-section {
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin: 8px 0;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
/* background: rgba(255, 255, 255, 0.06); */
|
||||
/* border-radius: 12px; */
|
||||
padding: 2px;
|
||||
/* margin: 8px 0; */
|
||||
/* border: 1px solid rgba(255, 255, 255, 0.08); */
|
||||
}
|
||||
|
||||
.battery-percentage {
|
||||
@@ -73,112 +38,74 @@
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
.battery-state {
|
||||
font-size: 0.9em;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.battery-time {
|
||||
font-size: 0.8em;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.battery-capacity {
|
||||
font-size: 0.8em;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.battery-temperature {
|
||||
font-size: 0.8em;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.battery-section-title {
|
||||
font-size: 0.95em;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin: 16px 0 8px 0;
|
||||
margin: 0px 10px;
|
||||
}
|
||||
|
||||
.battery-profiles-container {
|
||||
background: transparent;
|
||||
padding: 2px 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.battery-profile-button {
|
||||
#energy-mode-button-clickable {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 4px 6px;
|
||||
margin: 0 1px;
|
||||
border-radius: 8px;
|
||||
padding: 6px 12px;
|
||||
margin: 1px 0;
|
||||
transition: all 0.2s ease;
|
||||
min-width: 45px;
|
||||
}
|
||||
|
||||
.battery-profile-button:hover {
|
||||
#energy-mode-button-clickable:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.battery-profile-button.active {
|
||||
background: alpha(#2369ff, 0.2);
|
||||
#energy-mode-icon {
|
||||
border-radius: 50%;
|
||||
padding: 4px;
|
||||
margin-right: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.battery-profile-icon {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin-bottom: 2px;
|
||||
#energy-mode-icon.connected {
|
||||
background-color: #007aff;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.battery-profile-button.active .battery-profile-icon {
|
||||
color: rgba(0, 122, 255, 1);
|
||||
#energy-mode-button .battery-power-source {
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.battery-no-profiles {
|
||||
font-size: 0.85em;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* Gamemode Button Styles */
|
||||
.battery-gamemode-container {
|
||||
background: transparent;
|
||||
padding: 2px 8px;
|
||||
#game-mode-button {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.battery-gamemode-button {
|
||||
#game-mode-button-clickable {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 4px 6px;
|
||||
margin: 0 1px;
|
||||
border-radius: 8px;
|
||||
padding: 6px 12px;
|
||||
margin: 1px 0;
|
||||
transition: all 0.2s ease;
|
||||
min-width: 45px;
|
||||
/* min-height: 36px; */
|
||||
}
|
||||
|
||||
.battery-gamemode-button:hover {
|
||||
#game-mode-button-clickable:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.battery-gamemode-button.active {
|
||||
background: alpha(#2369ff, 0.2);
|
||||
/* background: rgba(255, 69, 0, 0.2); */
|
||||
#game-mode-icon {
|
||||
border-radius: 50%;
|
||||
padding: 4px;
|
||||
margin-right: 8px;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.battery-gamemode-icon {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.battery-gamemode-button.active .battery-gamemode-icon {
|
||||
color: rgba(255, 69, 0, 1);
|
||||
}
|
||||
|
||||
.battery-gamemode-label {
|
||||
font-size: 0.8em;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
#game-mode-icon.connected {
|
||||
background-color: #ff4500;
|
||||
color: #ffffff;
|
||||
}
|
||||
Reference in new issue
Block a user