13 Commits

Author SHA1 Message Date
112ca3e276 LiquidGUI [1.3.0.0]
- Linux fixes.
2025-02-11 23:31:37 +00:00
0f45cbf272 LiquidGUI [1.3.0.0]
- Continued refactoring.
2025-02-10 20:15:05 +00:00
89129fc6e5 LiquidGUI [1.3.0.0]
- Continued refactoring.
2025-02-10 20:13:22 +00:00
c05e8da224 LiquidGUI [1.3.0.0]
- Lots of refactoring.
2025-02-08 23:26:03 +00:00
ce4b1ec24c LiquidGUI [1.3.0.0]
- Moved CPU widget to top position.
2025-01-29 21:17:22 +00:00
aedd54b6a9 LiquidGUI [1.3.0.0]
- Unified Labels class to handle Linux and Windows.
2025-01-29 21:13:16 +00:00
3cf0709dd8 LiquidGUI [1.3.0.0]
- Round psutil result by 2 decimal places.
2025-01-27 00:24:57 +00:00
2226ebbe69 LiquidGUI [1.3.0.0]
- Initial psutil support for system vitals.
2025-01-27 00:17:44 +00:00
f9e01cfd8e LiquidGUI [1.2.0.0]
- Linux Support.
2024-12-30 14:38:47 +00:00
4d91e54e65 LiquidGUI [1.2.0.0]
- Linux Support
2024-12-30 14:08:06 +00:00
3cc53d0c81 LiquidGUI [1.2.0.0]
- Linux Support
2024-12-26 12:34:07 +00:00
03fca21675 LiquidGUI [1.2.0.0]
- Linux Support
2024-12-26 12:32:51 +00:00
040fff0677 LiquidGUI [1.2.0.0]
- Linux Support
2024-12-26 00:43:39 +00:00
15 changed files with 2969 additions and 54 deletions
+9 -1
View File
@@ -4,9 +4,17 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: LiquidCTL",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/main.pyw",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Python: Current File",
"type": "python",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
+1 -1
View File
@@ -6,6 +6,6 @@ class MessageHandler():
msg = QMessageBox()
msg.setWindowTitle("LiquidGUI Error")
msg.setText("No suitable devices could be detected. Please ensure you have a cooler \
both compatible with LiquidCTL, and connected to the system.")
compatible with LiquidCTL, and connected to the system.")
msg.setIcon(QMessageBox.Icon.Warning)
msg.exec()
Binary file not shown.
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
pyside6-rcc resources.qrc -o resources.py
pyinstaller main.pyw --onefile --icon resources/LiquidGUI.png --name LiquidGUI
+2 -2
View File
@@ -18,5 +18,5 @@ class MinMaxCurrent:
self.min = _cur
return (f"🟢 Current: {self.cur}{_unit}\n"
f"❄️ Min: {self.min}{_unit} / "
f"☀️ Max: {self.max}{_unit}")
f"Min: {self.min}{_unit} / "
f"Max: {self.max}{_unit}")
+8
View File
@@ -0,0 +1,8 @@
import platform
os = None
_platform = platform.platform()
if _platform.startswith("Linux"):
os = "Linux"
elif _platform.startswith("Windows"):
os = "Windows"
+33
View File
@@ -0,0 +1,33 @@
from interfaces.liquidctl_helper_interface import LiquidCTL_Helper_Interface
import subprocess
import re
class LiquidCTL_Helper(LiquidCTL_Helper_Interface):
device_name = str()
device_temp = 0
device_fanSpeed = 0
device_pumpSpeed = 0
device_fwVers = str()
devices = None
def ForceInit(self):
NotImplemented
def TestConnectionState(self):
output = subprocess.run(["liquidctl", "status"], stdout=subprocess.PIPE, universal_newlines=True)
if len(output.stdout) > 0:
return False
else:
return True
def Update(self):
output = subprocess.run(["liquidctl", "status"], stdout=subprocess.PIPE, universal_newlines=True)
self.device_name = str(re.search(r'^[^\n]*', output.stdout).group(0))
self.device_temp = float(re.search(r'Liquid temperature\s+(\d+\.?\d*)', output.stdout).group(1))
self.device_fanSpeed = int(re.search(r'Fan speed\s+(\d+)', output.stdout).group(1))
self.device_pumpSpeed = int(re.search(r'Pump speed\s+(\d+)', output.stdout).group(1))
def SetFanSpeed(self, speed):
NotImplemented
@@ -1,11 +1,12 @@
from liquidctl import find_liquidctl_devices, cli
from interfaces.liquidctl_helper_interface import LiquidCTL_Helper_Interface
from liquidctl import find_liquidctl_devices, cli # type: ignore
class LiquidCTL_Helper():
device_name = None
class LiquidCTL_Helper(LiquidCTL_Helper_Interface):
device_name = str()
device_temp = 0
device_fanSpeed = 0
device_pumpSpeed = 0
device_fwVers = None
device_fwVers = str()
devices = find_liquidctl_devices()
try:
+28
View File
@@ -0,0 +1,28 @@
from interfaces.vitals_helper_interface import VitalsHelperInterface
from enum import Enum
import psutil
class VitalsHelperLinux(VitalsHelperInterface):
class HWSensor(Enum):
lin_cpu_amd = ("k10temp", "Tctl")
lin_gpu_amd = ("amdgpu", "edge")
lin_mobo_asus = ("asus_wmi_sensors", "Motherboard Temperature")
def get_temps(self, _hw_sensor: HWSensor):
temps = psutil.sensors_temperatures()
if _hw_sensor.value[0] in temps:
for entry in temps[_hw_sensor.value[0]]:
if entry.label == _hw_sensor.value[1]:
return round(entry.current, 2)
class VitalsHelperWindows(VitalsHelperInterface):
def __init__(self):
print(f"{self.__class__.__name__} is not Implemented")
class HWSensor(Enum):
pass
def get_temps(self, _hw_sensor: HWSensor):
return 0
+48
View File
@@ -0,0 +1,48 @@
from abc import ABC, abstractmethod, abstractproperty
class LiquidCTL_Helper_Interface(ABC):
@property
@abstractmethod
def device_name(self) -> str:
pass
@property
@abstractmethod
def device_temp(self) -> float:
pass
@property
@abstractmethod
def device_fanSpeed(self) -> float:
pass
@property
@abstractmethod
def device_pumpSpeed(self) -> float:
pass
@property
@abstractmethod
def device_fwVers(self) -> str:
pass
@property
@abstractmethod
def devices(self) -> None:
pass
@abstractmethod
def ForceInit(self) -> None:
pass
@abstractmethod
def TestConnectionState(self) -> None:
pass
@abstractmethod
def Update(self) -> None:
pass
@abstractmethod
def SetFanSpeed(self, speed) -> None:
pass
+8
View File
@@ -0,0 +1,8 @@
from abc import ABC, abstractmethod
class VitalsHelperInterface(ABC):
@abstractmethod
def get_temps(self, HWSensor):
""" Return Temperatures """
pass
+93 -35
View File
@@ -1,16 +1,30 @@
# External Dependencies
# External Dependencies v####################################
import sys
import win32mica
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QProgressBar, QPushButton
from PySide6.QtCore import Qt, QTimer, QThreadPool
from PySide6.QtGui import QFont, QIcon
import darkdetect
# Internal Imports
from LiquidCTL_Helper import LiquidCTL_Helper
from MessageHandler import MessageHandler
from styles import Labels
from PySide6.QtWidgets import (QApplication,
QMainWindow,
QWidget,
QVBoxLayout,
QProgressBar,
QPushButton)
from PySide6.QtCore import (Qt,
QTimer,
QThreadPool)
from PySide6.QtGui import QIcon
## Internal Imports #########################################
import resources
import common
import resources, pkg_resources.extern
from MessageHandler import MessageHandler
## Platform Imports #########################################
import globals
from styles import Labels
if globals.os == "Windows":
from helpers.liquidctl_helper_windows import LiquidCTL_Helper
from helpers.vitals_helper import VitalsHelperWindows as VitalsHelper
import win32mica # type: ignore
import darkdetect # type: ignore
elif globals.os == "Linux":
from helpers.liquidctl_helper_linux import LiquidCTL_Helper
from helpers.vitals_helper import VitalsHelperLinux as VitalsHelper
class MainWindow(QMainWindow):
@@ -18,14 +32,22 @@ class MainWindow(QMainWindow):
def __init__(self, lctl):
super(MainWindow, self).__init__()
self.setWindowTitle("LiquidGUI (v.1.1.3.0)")
self.setFixedSize(450, 500)
self.setWindowTitle("LiquidGUI (v.1.3.0.0) DEV")
self.setFixedSize(450, 700)
self.lctl = lctl
self._lctl = lctl
self.__vitals_helper = VitalsHelper()
# Widgets ##########################################
self.lbl_device_name = Labels.MainLabel()
self.lbl_cpu_temp = Labels.SubLabel(value="💻 CPU Temp:")
self.min_max_cur_cpu_temp = common.MinMaxCurrent()
self.prg_cpu_temp = QProgressBar(textVisible=False,
minimum=0,
maximum=105)
self.lbl_value_prg_cpu_temp = Labels.SubLabelValue()
self.lbl_temp = Labels.SubLabel(value="💧 Liquid Temperature:")
self.min_max_cur_temp = common.MinMaxCurrent()
self.prg_temp = QProgressBar(textVisible=False,
@@ -46,6 +68,7 @@ class MainWindow(QMainWindow):
minimum=1900,
maximum=2700)
self.lbl_value_prg_pumpspeed = Labels.SubLabelValue()
self.btn_reset_min_max = QPushButton("Reset Min/Max")
self.btn_reset_min_max.clicked.connect(self.on_reset_min_max)
@@ -55,6 +78,9 @@ class MainWindow(QMainWindow):
widget = QWidget(self)
layout = QVBoxLayout(widget)
layout.addWidget(self.lbl_device_name)
layout.addWidget(self.lbl_cpu_temp)
layout.addWidget(self.prg_cpu_temp)
layout.addWidget(self.lbl_value_prg_cpu_temp)
layout.addWidget(self.lbl_temp)
layout.addWidget(self.prg_temp)
layout.addWidget(self.lbl_value_prg_temp)
@@ -73,12 +99,12 @@ class MainWindow(QMainWindow):
self.setCentralWidget(widget)
self.setContentsMargins(20, 20, 20, 20)
# Threading #######################################
# Threading #######################################################################
self.thread_manager = QThreadPool()
self.timer = QTimer()
self.timer.setInterval(1000)
self.timer.timeout.connect(lambda: self.thread_manager.start(self.lctl.Update))
self.timer.timeout.connect(lambda: self.thread_manager.start(self._lctl.Update))
self.timer.timeout.connect(self.update_widgets)
self.timer.start()
@@ -88,47 +114,79 @@ class MainWindow(QMainWindow):
self.min_max_cur_temp = common.MinMaxCurrent()
self.min_max_cur_fanspeed = common.MinMaxCurrent()
self.min_max_cur_pumpspeed = common.MinMaxCurrent()
self.min_max_cur_cpu_temp = common.MinMaxCurrent()
self.timer.start()
def update_widgets(self):
""" Update widgets using LiquidCTL library."""
self.lbl_device_name.setText(self.lctl.device_name)
self.prg_temp.setValue(self.lctl.device_temp)
# Platform Specific Widgets #######################################################
if globals.os == "Windows":
self.__vitals_helper()
elif globals.os == "Linux":
self.lbl_value_prg_cpu_temp.setText(
self.min_max_cur_cpu_temp.builder(
self.__vitals_helper.get_temps(
self.__vitals_helper.HWSensor.lin_cpu_amd), "°C"))
self.prg_cpu_temp.setValue(
self.__vitals_helper.get_temps(
self.__vitals_helper.HWSensor.lin_cpu_amd))
# Cross Platform Widgets ##########################################################
self.lbl_device_name.setText(
self._lctl.device_name)
self.prg_temp.setValue(
self._lctl.device_temp)
self.lbl_value_prg_temp.setText(
self.min_max_cur_temp.builder(
self.lctl.device_temp, "°C"))
self.prg_fanspeed.setValue(self.lctl.device_fanSpeed)
self._lctl.device_temp, "°C"))
self.prg_fanspeed.setValue(
self._lctl.device_fanSpeed)
self.lbl_value_prg_fanspeed.setText(
self.min_max_cur_fanspeed.builder(
self.lctl.device_fanSpeed, " rpm"))
self.prg_pumpspeed.setValue(self.lctl.device_pumpSpeed)
self._lctl.device_fanSpeed, " rpm"))
self.prg_pumpspeed.setValue(
self._lctl.device_pumpSpeed)
self.lbl_value_prg_pumpspeed.setText(
self.min_max_cur_pumpspeed.builder(
self.lctl.device_pumpSpeed, " rpm"))
if self.lctl.device_fwVers is not None:
self.lbl_fwvers.setText(f"Firmware: v{self.lctl.device_fwVers}")
self._lctl.device_pumpSpeed, " rpm"))
if len(self._lctl.device_fwVers) > 0:
self.lbl_fwvers.setText(f"Firmware: v{self._lctl.device_fwVers}")
def main():
""" Initialize application and setup window parameters. """
app = QApplication(sys.argv)
window = MainWindow(LiquidCTL_Helper())
if globals.os == "Windows":
window.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
icon = QIcon(":/icons/LiquidGUI.ico")
if darkdetect.isDark():
win32mica.ApplyMica(window.winId(), win32mica.MicaTheme.DARK)
elif darkdetect.isLight():
win32mica.ApplyMica(window.winId(), win32mica.MicaTheme.LIGHT)
elif globals.os == "Linux":
app.setDesktopFileName("LiquidGUI")
icon = QIcon(":/icons/LiquidGUI.png")
app.setWindowIcon(icon)
window = MainWindow(LiquidCTL_Helper())
window.setWindowIcon(icon)
window.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
# Show error and quit app if no devices are found
if window.lctl.TestConnectionState():
if window._lctl.TestConnectionState():
MessageHandler().ShowNoDevicesFoundError()
sys.exit(1)
else:
if darkdetect.isDark():
win32mica.ApplyMica(window.winId(), win32mica.MICAMODE.DARK)
elif darkdetect.isLight():
win32mica.ApplyMica(window.winId(), win32mica.MICAMODE.LIGHT)
window.show()
app.exec()
+2703 -3
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -2,5 +2,6 @@
<RCC version="1.0">
<qresource prefix="icons">
<file alias="LiquidGUI.ico">resources/LiquidGUI.ico</file>
<file alias="LiquidGUI.png">resources/LiquidGUI.png</file>
</qresource>
</RCC>
+26 -7
View File
@@ -1,27 +1,46 @@
from PySide6.QtWidgets import QLabel
from PySide6.QtGui import QFont
from PySide6.QtCore import Qt
import globals
def _set_os_family_font(ClassName: str):
_font = None
if globals.os == "Linux":
if ClassName == MainLabel.__name__ or SubLabel.__name__:
_font = "Noto Sans"
elif ClassName == SubLabelValue.__name__:
_font = "Noto Sans Mono"
elif globals.os == "Windows":
if ClassName == MainLabel.__name__ or SubLabel.__name__:
_font = "Calibri"
elif ClassName == SubLabelValue.__name__:
_font = "Cascadia Code"
return _font
class MainLabel(QLabel):
def __init__(self):
super().__init__()
self.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.setFont(QFont("Calibri",
18,
self.setFont(QFont(_set_os_family_font(__class__.__name__),
16,
weight=QFont.Weight.ExtraBold))
class SubLabel(QLabel):
""" Formatting for sub-labels. """
def __init__(self, value):
super().__init__()
self.setFont(QFont("Calibri", 12, weight=QFont.Weight.Thin))
self.setFont(QFont(_set_os_family_font(__class__.__name__),
12,
weight=QFont.Weight.Thin))
self.setText(value)
class SubLabelValue(QLabel):
""" Formatting for values. """
def __init__(self):
super().__init__()
self.setAlignment(Qt.AlignmentFlag.AlignRight)
self.setFont(QFont("Cascadia Code", 8))
self.setFont(QFont(_set_os_family_font(__class__.__name__), 8))