fix(gui): 🐛 integrate ansi2html for improved log message formatting

* Added `Ansi2HTMLConverter` to convert ANSI color codes in log messages to HTML.
* Updated the `MainWindow` class to utilize the new converter for displaying logs.
* Removed dependency on `coloredlogs.converter` for log message display.
This commit is contained in:
Robert Honz
2025-10-21 07:58:00 +02:00
parent 5c09b6594c
commit d3ec0398b4
3 changed files with 47 additions and 24 deletions
Generated
+37 -16
View File
@@ -1,5 +1,21 @@
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. # This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
[[package]]
name = "ansi2html"
version = "1.9.2"
description = "Convert text with ANSI color codes to HTML or to LaTeX"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "ansi2html-1.9.2-py3-none-any.whl", hash = "sha256:dccb75aa95fb018e5d299be2b45f802952377abfdce0504c17a6ee6ef0a420c5"},
{file = "ansi2html-1.9.2.tar.gz", hash = "sha256:3453bf87535d37b827b05245faaa756dbab4ec3d69925e352b6319c3c955c0a5"},
]
[package.extras]
docs = ["mkdocs", "mkdocs-material", "mkdocs-material-extensions", "mkdocstrings", "mkdocstrings-python", "pymdown-extensions"]
test = ["pytest", "pytest-cov"]
[[package]] [[package]]
name = "astroid" name = "astroid"
version = "4.0.1" version = "4.0.1"
@@ -633,14 +649,14 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2
[[package]] [[package]]
name = "iniconfig" name = "iniconfig"
version = "2.1.0" version = "2.3.0"
description = "brain-dead simple config-ini parsing" description = "brain-dead simple config-ini parsing"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.10"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"},
{file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"},
] ]
[[package]] [[package]]
@@ -1160,15 +1176,14 @@ files = [
] ]
[[package]] [[package]]
name = "nuitka" name = "Nuitka"
version = "2.8.3" version = "2.8.4"
description = "Python compiler with full language support and CPython compatibility" description = "Python compiler with full language support and CPython compatibility"
optional = false optional = false
python-versions = "*" python-versions = "*"
groups = ["dev"] groups = ["dev"]
files = [ files = []
{file = "Nuitka-2.8.3.tar.gz", hash = "sha256:10dc85443c49e7d6e4e8d3413cdfaefe7ebf3d8f47d2bfb5324b5676c3d77b5f"}, develop = false
]
[package.dependencies] [package.dependencies]
ordered-set = ">=4.1.0" ordered-set = ">=4.1.0"
@@ -1180,6 +1195,12 @@ build-wheel = ["setuptools (>=42)", "toml", "wheel"]
icon-conversion = ["imageio"] icon-conversion = ["imageio"]
onefile = ["zstandard (>=0.15)"] onefile = ["zstandard (>=0.15)"]
[package.source]
type = "git"
url = "https://github.com/Nuitka/Nuitka.git"
reference = "2.8.4"
resolved_reference = "fa3c20ac628e9652f58cff9558ae066c7a500ca0"
[[package]] [[package]]
name = "ordered-set" name = "ordered-set"
version = "4.1.0" version = "4.1.0"
@@ -1528,14 +1549,14 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]] [[package]]
name = "pylint" name = "pylint"
version = "4.0.1" version = "4.0.2"
description = "python code static checker" description = "python code static checker"
optional = false optional = false
python-versions = ">=3.10.0" python-versions = ">=3.10.0"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "pylint-4.0.1-py3-none-any.whl", hash = "sha256:6077ac21d01b7361eae6ed0f38d9024c02732fdc635d9e154d4fe6063af8ac56"}, {file = "pylint-4.0.2-py3-none-any.whl", hash = "sha256:9627ccd129893fb8ee8e8010261cb13485daca83e61a6f854a85528ee579502d"},
{file = "pylint-4.0.1.tar.gz", hash = "sha256:06db6a1fda3cedbd7aee58f09d241e40e5f14b382fd035ed97be320f11728a84"}, {file = "pylint-4.0.2.tar.gz", hash = "sha256:9c22dfa52781d3b79ce86ab2463940f874921a3e5707bcfc98dd0c019945014e"},
] ]
[package.dependencies] [package.dependencies]
@@ -2095,14 +2116,14 @@ virtualenv = ">=20.34"
[[package]] [[package]]
name = "typer" name = "typer"
version = "0.19.2" version = "0.20.0"
description = "Typer, build great CLIs. Easy to code. Based on Python type hints." description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "typer-0.19.2-py3-none-any.whl", hash = "sha256:755e7e19670ffad8283db353267cb81ef252f595aa6834a0d1ca9312d9326cb9"}, {file = "typer-0.20.0-py3-none-any.whl", hash = "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a"},
{file = "typer-0.19.2.tar.gz", hash = "sha256:9ad824308ded0ad06cc716434705f691d4ee0bfd0fb081839d2e426860e7fdca"}, {file = "typer-0.20.0.tar.gz", hash = "sha256:1aaf6494031793e4876fb0bacfa6a912b551cf43c1e63c800df8b1a866720c37"},
] ]
[package.dependencies] [package.dependencies]
@@ -2339,4 +2360,4 @@ gui = ["pyqtdarktheme-fork", "pyside6"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">=3.12,<3.14" python-versions = ">=3.12,<3.14"
content-hash = "df2d544dcb81e9722b5eb931b6e3d1f045052f31b5ce0f9e5e92f7a7d8aefbe8" content-hash = "73a9195e1d46d0176c01c731c1431d4b43085376485622d33e0efd53c42e2fb1"
+3 -3
View File
@@ -11,7 +11,6 @@ classifiers = [
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
] ]
requires-python = ">=3.12,<3.14" requires-python = ">=3.12,<3.14"
dynamic = ["dependencies"] dynamic = ["dependencies"]
@@ -40,10 +39,11 @@ pyside6 = { version = "6.10.0", optional = true }
pyqtdarktheme-fork = { version = "^2.3.4", optional = true } pyqtdarktheme-fork = { version = "^2.3.4", optional = true }
rich = "^14.2.0" rich = "^14.2.0"
toml = "^0.10.2" toml = "^0.10.2"
typer = "^0.19.2" typer = "^0.20.0"
tidalapi = "^0.8.8" tidalapi = "^0.8.8"
python-ffmpeg = "^2.0.12" python-ffmpeg = "^2.0.12"
pycryptodome = "^3.23.0" pycryptodome = "^3.23.0"
ansi2html = "^1.9.2"
[project.optional-dependencies] [project.optional-dependencies]
gui = ["pyside6", "pyqtdarktheme-fork"] gui = ["pyside6", "pyqtdarktheme-fork"]
@@ -67,7 +67,7 @@ pylint = "^4.0.1"
pillow = "^12.0.0" pillow = "^12.0.0"
pytest-cov = "^7.0.0" pytest-cov = "^7.0.0"
black = "^25.9.0" black = "^25.9.0"
nuitka = "^2.8.3" nuitka = { git = "https://github.com/Nuitka/Nuitka.git", tag = "2.8.4" }
[tool.poetry.group.docs] [tool.poetry.group.docs]
optional = true optional = true
+7 -5
View File
@@ -89,7 +89,8 @@ except ImportError as e:
print("Qt dependencies missing. Cannot start GUI. Please read the 'README.md' carefully.") print("Qt dependencies missing. Cannot start GUI. Please read the 'README.md' carefully.")
sys.exit(1) sys.exit(1)
import coloredlogs.converter
from ansi2html import Ansi2HTMLConverter
from rich.progress import Progress from rich.progress import Progress
from tidalapi import Album, Mix, Playlist, Quality, Track, UserPlaylist, Video from tidalapi import Album, Mix, Playlist, Quality, Track, UserPlaylist, Video
from tidalapi.artist import Artist from tidalapi.artist import Artist
@@ -143,6 +144,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
s_queue_download_item_finished: QtCore.Signal = QtCore.Signal(object) s_queue_download_item_finished: QtCore.Signal = QtCore.Signal(object)
s_queue_download_item_failed: QtCore.Signal = QtCore.Signal(object) s_queue_download_item_failed: QtCore.Signal = QtCore.Signal(object)
s_queue_download_item_skipped: QtCore.Signal = QtCore.Signal(object) s_queue_download_item_skipped: QtCore.Signal = QtCore.Signal(object)
converter_ansi_html: Ansi2HTMLConverter
def __init__(self, tidal: Tidal | None = None) -> None: def __init__(self, tidal: Tidal | None = None) -> None:
"""Initialize the main window and all components. """Initialize the main window and all components.
@@ -187,6 +189,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.settings.data.window_h, self.settings.data.window_h,
) )
self.spinners: dict[QtWidgets.QWidget, QtWaitingSpinner] = {} self.spinners: dict[QtWidgets.QWidget, QtWaitingSpinner] = {}
self.converter_ansi_html: Ansi2HTMLConverter = Ansi2HTMLConverter()
def init_tidal(self, tidal: Tidal | None = None): def init_tidal(self, tidal: Tidal | None = None):
"""Initialize Tidal session and handle login flow. """Initialize Tidal session and handle login flow.
@@ -297,12 +300,11 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
Args: Args:
text (str): Log message. text (str): Log message.
""" """
display_msg = coloredlogs.converter.convert(text)
cursor: QtGui.QTextCursor = self.te_debug.textCursor() cursor: QtGui.QTextCursor = self.te_debug.textCursor()
cursor.movePosition(QtGui.QTextCursor.End) html = self.converter_ansi_html.convert(text)
cursor.insertHtml(display_msg)
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertHtml(html)
self.te_debug.setTextCursor(cursor) self.te_debug.setTextCursor(cursor)
self.te_debug.ensureCursorVisible() self.te_debug.ensureCursorVisible()