chore(release): v0.7.6

Ajoute un fichier log texte rotatif (wgsecure.log) dans le dossier
applicatif, en complément du journal JSON interne, pour diagnostiquer
un échec (ex. split-DNS) sans dépendre de l'UI. Corrige le panneau
Journal qui coupait les messages longs sans moyen de les lire en
entier (défilement horizontal réactivé + infobulle).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 15:25:01 +02:00
co-authored by Claude Sonnet 5
parent 66faf5e661
commit 6a3e8700c3
7 changed files with 56 additions and 6 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
__version__ = "0.7.5"
__version__ = "0.7.6"
APP_NAME = "WGSecure"
APP_SHORT = "WGS"
+36
View File
@@ -1,17 +1,48 @@
"""Journal des événements de connexion WGSecure."""
import os
import json
import logging
from datetime import datetime
from logging.handlers import RotatingFileHandler
from app.utils.platform_utils import get_config_dir
_FILE = "events.json"
_MAX_ENTRIES = 200
_LOG_FILE = "wgsecure.log"
_LOG_LEVELS = {
"error": logging.ERROR,
"warning": logging.WARNING,
}
_file_logger: logging.Logger | None = None
def _path() -> str:
return os.path.join(get_config_dir(), _FILE)
def _get_file_logger() -> logging.Logger:
"""Logger fichier rotatif : trace texte des opérations, lisible sans
passer par l'UI (diagnostic d'un échec quand le panneau Journal ne
suffit pas)."""
global _file_logger
if _file_logger is None:
logger = logging.getLogger("wgsecure")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(
os.path.join(get_config_dir(), _LOG_FILE),
maxBytes=1_000_000, backupCount=3, encoding="utf-8",
)
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S",
))
logger.addHandler(handler)
logger.propagate = False
_file_logger = logger
return _file_logger
def log_event(msg: str, kind: str = "info") -> None:
"""Ajoute un événement horodaté au journal."""
events = _load()
@@ -21,6 +52,11 @@ def log_event(msg: str, kind: str = "info") -> None:
"msg": msg,
})
_save(events[-_MAX_ENTRIES:])
# Une ligne = un événement, même si msg contient des retours à la ligne
# (ex. message de succès de connexion suivi d'un avertissement).
_get_file_logger().log(
_LOG_LEVELS.get(kind, logging.INFO), msg.replace("\n", " | ")
)
def get_events(n: int = 50) -> list[dict]:
+5 -1
View File
@@ -138,7 +138,7 @@ class MainWindow(QMainWindow):
" border: none; font-size: 10px; font-family: Courier; }"
"QListWidget::item { padding: 1px 6px; }"
)
self._log_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self._log_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
d.addWidget(self._log_list)
d.addWidget(self._hsep())
@@ -454,6 +454,10 @@ class MainWindow(QMainWindow):
color = theme.LOG_COLORS.get(kind, theme.ACCENT_LIGHT)
item = QListWidgetItem(f"[{ts}] {msg}")
item.setForeground(QColor(color))
# Ligne trop longue pour tenir dans le panneau : barre de défilement
# horizontale (ci-dessus) + tooltip pour lire le message complet
# sans avoir à défiler.
item.setToolTip(msg)
self._log_list.addItem(item)
self._log_list.scrollToBottom()