windows dark mode styling, this reads the registry, some scrollbar styles. and a new and improved logo
All checks were successful
Build MuCaPy Executable / build-and-package (push) Successful in 2m4s
All checks were successful
Build MuCaPy Executable / build-and-package (push) Successful in 2m4s
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
import json
|
import json
|
||||||
|
import winreg
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import ctypes
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import psutil # Add psutil import
|
import psutil # Add psutil import
|
||||||
@@ -1189,7 +1190,7 @@ class AboutWindow(QDialog):
|
|||||||
layout.addWidget(icon_label)
|
layout.addWidget(icon_label)
|
||||||
|
|
||||||
# Title
|
# Title
|
||||||
title_label = QLabel("MuCaPy - 1")
|
title_label = QLabel("PySec")
|
||||||
title_label.setStyleSheet("font-size: 18px; font-weight: bold;")
|
title_label.setStyleSheet("font-size: 18px; font-weight: bold;")
|
||||||
title_label.setAlignment(Qt.AlignCenter)
|
title_label.setAlignment(Qt.AlignCenter)
|
||||||
layout.addWidget(title_label)
|
layout.addWidget(title_label)
|
||||||
@@ -1886,7 +1887,7 @@ class CameraSelectorDialog(QDialog):
|
|||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setWindowTitle("MuCaPy - V1")
|
self.setWindowTitle("PySec")
|
||||||
self.setGeometry(100, 100, 1200, 800)
|
self.setGeometry(100, 100, 1200, 800)
|
||||||
|
|
||||||
# Initialize configuration
|
# Initialize configuration
|
||||||
@@ -2404,7 +2405,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Python Memory Usage
|
# Python Memory Usage
|
||||||
mem_layout = QHBoxLayout()
|
mem_layout = QHBoxLayout()
|
||||||
mem_layout.addWidget(QLabel("Python Memory:"))
|
mem_layout.addWidget(QLabel("RAM-Usage:"))
|
||||||
self.mem_progress = QProgressBar()
|
self.mem_progress = QProgressBar()
|
||||||
self.mem_progress.setRange(0, 100)
|
self.mem_progress.setRange(0, 100)
|
||||||
self.mem_progress.setTextVisible(True)
|
self.mem_progress.setTextVisible(True)
|
||||||
@@ -2686,14 +2687,14 @@ class MainWindow(QMainWindow):
|
|||||||
available = vm.available # bytes available to processes without swapping
|
available = vm.available # bytes available to processes without swapping
|
||||||
total_ram = vm.total
|
total_ram = vm.total
|
||||||
# Calculate percent of available memory currently occupied by this process
|
# Calculate percent of available memory currently occupied by this process
|
||||||
mem_percent = int(min((rss / available) * 100, 100)) if available else 0
|
mem_percent = int(min((rss / available) * 500, 100)) if available else 0
|
||||||
if hasattr(self, 'mem_progress'):
|
if hasattr(self, 'mem_progress'):
|
||||||
# Update bar value and dynamic text
|
# Update bar value and dynamic text
|
||||||
self.mem_progress.setValue(mem_percent)
|
self.mem_progress.setValue(mem_percent)
|
||||||
rss_h = bytes_to_human(rss)
|
rss_h = bytes_to_human(rss)
|
||||||
avail_h = bytes_to_human(available)
|
avail_h = bytes_to_human(available)
|
||||||
self.mem_progress.setFormat(f"{mem_percent}%")
|
self.mem_progress.setFormat(f"{rss_h}")
|
||||||
self.mem_progress.setToolTip(f"Python RSS: {rss_h}\nAvailable: {avail_h}\nTotal RAM: {bytes_to_human(total_ram)}")
|
self.mem_progress.setToolTip(f"Python Resident Set Size: {rss_h}\nAvailable: {avail_h}\nTotal RAM: {bytes_to_human(total_ram)}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2818,29 +2819,88 @@ class initQT:
|
|||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__ == "__main__":
|
"""
|
||||||
|
This is where windows fuckery starts, if you try to modify any of this then good luck,
|
||||||
|
this code is fragile but usually works, idk if it works in production but im pushing anyways,
|
||||||
|
fuck you.
|
||||||
|
Here we just try to set the windows titlebar to dark mode, this is done with HWND Handle
|
||||||
|
"""
|
||||||
|
def is_windows_darkmode() -> bool:
|
||||||
|
if platform.system() != "Windows":
|
||||||
|
return False
|
||||||
|
|
||||||
# Initialize Qt if on Linux ; If shit fails then modify these Functions
|
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
|
||||||
|
|
||||||
|
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:
|
||||||
|
set_dark_titlebar(receiver)
|
||||||
|
return super().notify(receiver, event)
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Initialize Qt if on Linux
|
||||||
if platform.system() == "Linux":
|
if platform.system() == "Linux":
|
||||||
qt = initQT()
|
qt = initQT()
|
||||||
qt.getenv()
|
qt.getenv()
|
||||||
qt.setenv()
|
qt.setenv()
|
||||||
qt.shutupCV()
|
qt.shutupCV()
|
||||||
else:
|
|
||||||
# We do nothing, Windows doesnt need this ; better shit anyways
|
|
||||||
pass
|
|
||||||
|
|
||||||
app = QApplication(sys.argv)
|
app = darkmodechildren(sys.argv)
|
||||||
|
|
||||||
# Here we try to set the AppIcon ; If it isnt find then just pass
|
# Try to set the AppIcon
|
||||||
try:
|
try:
|
||||||
app.setWindowIcon(QIcon(getpath.resource_path("styling/icon.png")))
|
app.setWindowIcon(QIcon(getpath.resource_path("styling/icon.png")))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Set application style to Fusion for better dark mode support
|
# Use Fusion style for consistent dark-mode palettes
|
||||||
app.setStyle("Fusion")
|
app.setStyle("Fusion")
|
||||||
|
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
window.show()
|
window.show()
|
||||||
|
|
||||||
|
try:
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exit Exception with: {e}")
|
||||||
|
pass
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -93,3 +93,66 @@ QToolButton {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScrollBar:vertical {
|
||||||
|
background: #1E1E1E; /* Scrollbar background */
|
||||||
|
width: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical {
|
||||||
|
background: #3A3A3A; /* Scroll handle */
|
||||||
|
min-height: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:hover {
|
||||||
|
background: #555555; /* Hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:pressed {
|
||||||
|
background: #6A6A6A; /* Active color */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:vertical,
|
||||||
|
QScrollBar::sub-line:vertical {
|
||||||
|
height: 0px; /* Hide arrows */
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:vertical,
|
||||||
|
QScrollBar::sub-page:vertical {
|
||||||
|
background: none; /* No gap color */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== Horizontal Scrollbar ===== */
|
||||||
|
QScrollBar:horizontal {
|
||||||
|
background: #1E1E1E;
|
||||||
|
height: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal {
|
||||||
|
background: #3A3A3A;
|
||||||
|
min-width: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:hover {
|
||||||
|
background: #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:pressed {
|
||||||
|
background: #6A6A6A;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:horizontal,
|
||||||
|
QScrollBar::sub-line:horizontal {
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:horizontal,
|
||||||
|
QScrollBar::sub-page:horizontal {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user