97 lines
3.3 KiB
Python
97 lines
3.3 KiB
Python
import os
|
|
import platform
|
|
try:
|
|
import winreg
|
|
except ImportError:
|
|
pass
|
|
import ctypes
|
|
from PyQt5.QtWidgets import QWidget, QApplication
|
|
from PyQt5.QtCore import QEvent
|
|
|
|
class conversion:
|
|
_symbols = ("B", "KiB", "MiB", "GiB", "TiB", "PiB")
|
|
_thresholds = [1 << (10 * i) for i in range(len(_symbols))]
|
|
|
|
@staticmethod
|
|
def bytes_to_human(n: int) -> str:
|
|
try:
|
|
n = int(n)
|
|
except Exception:
|
|
return str(n)
|
|
|
|
if n < 1024:
|
|
return f"{n} B"
|
|
|
|
thresholds = conversion._thresholds
|
|
symbols = conversion._symbols
|
|
i = min(len(thresholds) - 1, (n.bit_length() - 1) // 10)
|
|
val = n / thresholds[i]
|
|
|
|
# Pick a faster formatting branch
|
|
if val >= 100:
|
|
return f"{val:.0f} {symbols[i]}"
|
|
elif val >= 10:
|
|
return f"{val:.1f} {symbols[i]}"
|
|
else:
|
|
return f"{val:.2f} {symbols[i]}"
|
|
|
|
class getpath:
|
|
@staticmethod
|
|
def resource_path(relative_path: str):
|
|
base_path = os.path.dirname(os.path.abspath(__file__))
|
|
return os.path.join(base_path, relative_path)
|
|
|
|
class windows:
|
|
@staticmethod
|
|
def is_windows_darkmode() -> bool:
|
|
if platform.system() != "Windows":
|
|
return False
|
|
|
|
try:
|
|
key_path = r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"
|
|
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path) as key:
|
|
# 0 = dark mode, 1 = light mode
|
|
value, _ = winreg.QueryValueEx(key, "AppsUseLightTheme")
|
|
# print(f"AppsUseLightTheme: {value}") # optional debug
|
|
return value == 0
|
|
except Exception as e:
|
|
print(f"Could not read Windows registry for dark mode: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def set_dark_titlebar(widget: QWidget):
|
|
"""Apply dark titlebar on Windows to any top-level window."""
|
|
if platform.system() != "Windows":
|
|
return
|
|
if not widget.isWindow(): # only top-level windows
|
|
return
|
|
if windows.is_windows_darkmode():
|
|
try:
|
|
hwnd = int(widget.winId())
|
|
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
|
|
value = ctypes.c_int(1)
|
|
res = ctypes.windll.dwmapi.DwmSetWindowAttribute(
|
|
hwnd,
|
|
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
|
ctypes.byref(value),
|
|
ctypes.sizeof(value)
|
|
)
|
|
if res != 0:
|
|
# fallback for some Windows builds
|
|
DWMWA_USE_IMMERSIVE_DARK_MODE = 19
|
|
ctypes.windll.dwmapi.DwmSetWindowAttribute(
|
|
hwnd,
|
|
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
|
ctypes.byref(value),
|
|
ctypes.sizeof(value)
|
|
)
|
|
except Exception as e:
|
|
print("Failed to set dark titlebar:", e)
|
|
|
|
class darkmodechildren(QApplication):
|
|
def notify(self, receiver, event):
|
|
# Only handle top-level windows
|
|
if isinstance(receiver, QWidget) and receiver.isWindow():
|
|
if event.type() == QEvent.WinIdChange:
|
|
windows.set_dark_titlebar(receiver)
|
|
return super().notify(receiver, event) |