Bouton Retour visible + menu config admin
- Bouton "< Retour" gros en haut à gauche sur chaque page d'instructions - Appui long (5 sec) sur le titre "Photostation" = ouvre config admin - Config : nom WiFi, mot de passe, URL QR, adresse email, imprimante CUPS - Config sauvegardée dans config/settings.json - Labels WiFi/QR/Email mis à jour dynamiquement depuis la config Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,16 +2,13 @@
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel,
|
||||
QStackedWidget, QSizePolicy
|
||||
QStackedWidget
|
||||
)
|
||||
from PyQt6.QtCore import Qt, QTimer
|
||||
from PyQt6.QtGui import QFont, QPixmap, QImage
|
||||
from PyQt6.QtCore import Qt, QTimer, QElapsedTimer
|
||||
from PyQt6.QtGui import QFont, QPixmap, QImage, QMouseEvent
|
||||
|
||||
from services.usb_watcher import UsbWatcher
|
||||
|
||||
WIFI_AP_NAME = "Photostation"
|
||||
WIFI_AP_PASSWORD = "photo1234"
|
||||
EMAIL_ADDRESS = "photo@photostation.local"
|
||||
from ui.widgets.config_dialog import load_config, ConfigDialog
|
||||
|
||||
BTN_STYLE = """
|
||||
QPushButton {{
|
||||
@@ -31,19 +28,13 @@ BACK_BTN_STYLE = """
|
||||
QPushButton {
|
||||
background-color: #757575;
|
||||
color: white;
|
||||
border-radius: 10px;
|
||||
padding: 10px 30px;
|
||||
border-radius: 12px;
|
||||
padding: 12px 30px;
|
||||
font-size: 16px;
|
||||
}
|
||||
QPushButton:pressed { background-color: #616161; }
|
||||
"""
|
||||
|
||||
INFO_STYLE = """
|
||||
QLabel {
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
"""
|
||||
|
||||
HIGHLIGHT_STYLE = """
|
||||
QLabel {
|
||||
background-color: #E3F2FD;
|
||||
@@ -75,6 +66,36 @@ SUCCESS_STYLE = """
|
||||
}
|
||||
"""
|
||||
|
||||
INFO_STYLE = """
|
||||
QLabel {
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class LongPressLabel(QLabel):
|
||||
"""QLabel qui détecte l'appui long (5 sec) pour ouvrir la config."""
|
||||
|
||||
def __init__(self, text, callback, parent=None):
|
||||
super().__init__(text, parent)
|
||||
self._callback = callback
|
||||
self._press_timer = QElapsedTimer()
|
||||
self._long_press_timer = QTimer(self)
|
||||
self._long_press_timer.setSingleShot(True)
|
||||
self._long_press_timer.timeout.connect(self._on_long_press)
|
||||
|
||||
def mousePressEvent(self, event: QMouseEvent):
|
||||
self._long_press_timer.start(5000)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event: QMouseEvent):
|
||||
self._long_press_timer.stop()
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
def _on_long_press(self):
|
||||
self._callback()
|
||||
|
||||
|
||||
class HomeScreen(QWidget):
|
||||
def __init__(self, main_window):
|
||||
@@ -82,34 +103,46 @@ class HomeScreen(QWidget):
|
||||
self.main_window = main_window
|
||||
self._usb_photos = []
|
||||
self._usb_mount = None
|
||||
self.config = load_config()
|
||||
self._setup_ui()
|
||||
self._setup_usb_watcher()
|
||||
|
||||
def _setup_ui(self):
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(20, 20, 20, 20)
|
||||
layout.setSpacing(20)
|
||||
layout.setContentsMargins(20, 15, 20, 15)
|
||||
layout.setSpacing(10)
|
||||
|
||||
# Titre (toujours visible)
|
||||
title = QLabel("Photostation")
|
||||
title.setFont(QFont("", 42, QFont.Weight.Bold))
|
||||
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
# Titre (appui long 5s = config)
|
||||
self.title = LongPressLabel("Photostation", self._open_config)
|
||||
self.title.setFont(QFont("", 42, QFont.Weight.Bold))
|
||||
self.title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(self.title)
|
||||
|
||||
# Zone switchable : choix des modes OU instructions d'un mode
|
||||
# Zone switchable
|
||||
self.stack = QStackedWidget()
|
||||
layout.addWidget(self.stack, 1)
|
||||
|
||||
# Page 0 : Choix des modes
|
||||
self.stack.addWidget(self._build_mode_selection())
|
||||
# Page 1 : Instructions USB
|
||||
self.stack.addWidget(self._build_usb_instructions())
|
||||
# Page 2 : Instructions WiFi
|
||||
self.stack.addWidget(self._build_wifi_instructions())
|
||||
# Page 3 : Instructions QR Code
|
||||
self.stack.addWidget(self._build_qr_instructions())
|
||||
# Page 4 : Instructions Email
|
||||
self.stack.addWidget(self._build_email_instructions())
|
||||
# Pages
|
||||
self.stack.addWidget(self._build_mode_selection()) # 0
|
||||
self.stack.addWidget(self._build_usb_page()) # 1
|
||||
self.stack.addWidget(self._build_wifi_page()) # 2
|
||||
self.stack.addWidget(self._build_qr_page()) # 3
|
||||
self.stack.addWidget(self._build_email_page()) # 4
|
||||
|
||||
def _make_back_button(self):
|
||||
btn = QPushButton("< Retour")
|
||||
btn.setFont(QFont("", 16, QFont.Weight.Bold))
|
||||
btn.setMinimumSize(150, 55)
|
||||
btn.setStyleSheet(BACK_BTN_STYLE)
|
||||
btn.clicked.connect(self._show_modes)
|
||||
return btn
|
||||
|
||||
def _make_page_header(self):
|
||||
"""Header commun : gros bouton Retour en haut à gauche."""
|
||||
header = QHBoxLayout()
|
||||
header.addWidget(self._make_back_button())
|
||||
header.addStretch()
|
||||
return header
|
||||
|
||||
# ─── Page 0 : Sélection des modes ───
|
||||
|
||||
@@ -129,7 +162,7 @@ class HomeScreen(QWidget):
|
||||
|
||||
modes = [
|
||||
("USB", "Clé USB", self._show_usb),
|
||||
("WiFi", "Depuis téléphone", self._show_wifi),
|
||||
("WiFi", "Depuis\ntéléphone", self._show_wifi),
|
||||
("QR Code", "Scanner pour\nenvoyer", self._show_qr),
|
||||
("Email", "Recevoir par\nmail", self._show_email),
|
||||
]
|
||||
@@ -145,31 +178,39 @@ class HomeScreen(QWidget):
|
||||
self.mode_buttons[label] = btn
|
||||
|
||||
layout.addLayout(buttons_layout)
|
||||
|
||||
# Hint config
|
||||
hint = QLabel("Appui long sur le titre pour accéder à la configuration")
|
||||
hint.setFont(QFont("", 10))
|
||||
hint.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
hint.setStyleSheet("color: #bbb;")
|
||||
layout.addWidget(hint)
|
||||
|
||||
return page
|
||||
|
||||
# ─── Page 1 : USB ───
|
||||
|
||||
def _build_usb_instructions(self):
|
||||
def _build_usb_page(self):
|
||||
page = QWidget()
|
||||
layout = QVBoxLayout(page)
|
||||
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.setSpacing(25)
|
||||
layout.setSpacing(20)
|
||||
|
||||
layout.addLayout(self._make_page_header())
|
||||
|
||||
# Instruction principale
|
||||
instruction = QLabel("Insérez votre clé USB dans le port\nde la borne")
|
||||
instruction.setFont(QFont("", 24))
|
||||
instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(instruction)
|
||||
|
||||
# Zone de status (change dynamiquement)
|
||||
self.usb_status_label = QLabel("En attente de la clé USB...")
|
||||
layout.addStretch()
|
||||
|
||||
self.usb_status_label = QLabel("Clé USB non détectée\nInsérez votre clé USB puis patientez quelques secondes")
|
||||
self.usb_status_label.setFont(QFont("", 18))
|
||||
self.usb_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.usb_status_label.setMinimumHeight(70)
|
||||
self.usb_status_label.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
self.usb_status_label.setMinimumHeight(80)
|
||||
self.usb_status_label.setStyleSheet(ERROR_STYLE)
|
||||
layout.addWidget(self.usb_status_label)
|
||||
|
||||
# Bouton continuer (masqué tant que pas de clé)
|
||||
self.usb_continue_btn = QPushButton("Continuer")
|
||||
self.usb_continue_btn.setFont(QFont("", 18, QFont.Weight.Bold))
|
||||
self.usb_continue_btn.setMinimumSize(250, 60)
|
||||
@@ -178,46 +219,36 @@ class HomeScreen(QWidget):
|
||||
self.usb_continue_btn.hide()
|
||||
layout.addWidget(self.usb_continue_btn, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
# Bouton retour
|
||||
back = QPushButton("Retour")
|
||||
back.setFont(QFont("", 14))
|
||||
back.setStyleSheet(BACK_BTN_STYLE)
|
||||
back.clicked.connect(self._show_modes)
|
||||
layout.addWidget(back, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
layout.addStretch()
|
||||
return page
|
||||
|
||||
# ─── Page 2 : WiFi ───
|
||||
|
||||
def _build_wifi_instructions(self):
|
||||
def _build_wifi_page(self):
|
||||
page = QWidget()
|
||||
layout = QVBoxLayout(page)
|
||||
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.setSpacing(25)
|
||||
layout.setSpacing(20)
|
||||
|
||||
layout.addLayout(self._make_page_header())
|
||||
|
||||
instruction = QLabel("Connectez-vous au réseau WiFi\nde la borne depuis votre téléphone")
|
||||
instruction.setFont(QFont("", 24))
|
||||
instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(instruction)
|
||||
|
||||
# Infos réseau
|
||||
info_box = QWidget()
|
||||
info_layout = QVBoxLayout(info_box)
|
||||
info_layout.setSpacing(10)
|
||||
layout.addStretch()
|
||||
|
||||
net_name = QLabel(f"Nom du réseau : {WIFI_AP_NAME}")
|
||||
net_name.setFont(QFont("", 22, QFont.Weight.Bold))
|
||||
net_name.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
net_name.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
info_layout.addWidget(net_name)
|
||||
self.wifi_name_label = QLabel(f"Nom du réseau : {self.config['wifi_ap_name']}")
|
||||
self.wifi_name_label.setFont(QFont("", 22, QFont.Weight.Bold))
|
||||
self.wifi_name_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.wifi_name_label.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
layout.addWidget(self.wifi_name_label)
|
||||
|
||||
net_pass = QLabel(f"Mot de passe : {WIFI_AP_PASSWORD}")
|
||||
net_pass.setFont(QFont("", 22, QFont.Weight.Bold))
|
||||
net_pass.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
net_pass.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
info_layout.addWidget(net_pass)
|
||||
|
||||
layout.addWidget(info_box)
|
||||
self.wifi_pass_label = QLabel(f"Mot de passe : {self.config['wifi_ap_password']}")
|
||||
self.wifi_pass_label.setFont(QFont("", 22, QFont.Weight.Bold))
|
||||
self.wifi_pass_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.wifi_pass_label.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
layout.addWidget(self.wifi_pass_label)
|
||||
|
||||
step2 = QLabel("Une fois connecté, une page s'ouvrira\nautomatiquement pour envoyer vos photos")
|
||||
step2.setFont(QFont("", 16))
|
||||
@@ -225,42 +256,35 @@ class HomeScreen(QWidget):
|
||||
step2.setStyleSheet("color: #666;")
|
||||
layout.addWidget(step2)
|
||||
|
||||
# Status connexions
|
||||
self.wifi_status_label = QLabel("En attente de connexion...")
|
||||
self.wifi_status_label.setFont(QFont("", 16))
|
||||
self.wifi_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.wifi_status_label.setStyleSheet(INFO_STYLE)
|
||||
layout.addWidget(self.wifi_status_label)
|
||||
|
||||
back = QPushButton("Retour")
|
||||
back.setFont(QFont("", 14))
|
||||
back.setStyleSheet(BACK_BTN_STYLE)
|
||||
back.clicked.connect(self._show_modes)
|
||||
layout.addWidget(back, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
layout.addStretch()
|
||||
return page
|
||||
|
||||
# ─── Page 3 : QR Code ───
|
||||
|
||||
def _build_qr_instructions(self):
|
||||
def _build_qr_page(self):
|
||||
page = QWidget()
|
||||
layout = QVBoxLayout(page)
|
||||
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.setSpacing(20)
|
||||
layout.setSpacing(15)
|
||||
|
||||
layout.addLayout(self._make_page_header())
|
||||
|
||||
instruction = QLabel("Scannez ce QR code avec votre téléphone\npour envoyer vos photos")
|
||||
instruction.setFont(QFont("", 24))
|
||||
instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(instruction)
|
||||
|
||||
# QR Code affiché
|
||||
self.qr_image_label = QLabel()
|
||||
self.qr_image_label.setFixedSize(250, 250)
|
||||
self.qr_image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.qr_image_label.setStyleSheet("background-color: white; border: 2px solid #ccc; border-radius: 10px;")
|
||||
layout.addWidget(self.qr_image_label, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
# URL affichée en texte aussi
|
||||
self.qr_url_label = QLabel("")
|
||||
self.qr_url_label.setFont(QFont("", 14))
|
||||
self.qr_url_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
@@ -273,40 +297,35 @@ class HomeScreen(QWidget):
|
||||
hint.setStyleSheet("color: #666;")
|
||||
layout.addWidget(hint)
|
||||
|
||||
# Status réception
|
||||
self.qr_status_label = QLabel("En attente de photos...")
|
||||
self.qr_status_label.setFont(QFont("", 16))
|
||||
self.qr_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.qr_status_label.setStyleSheet(INFO_STYLE)
|
||||
layout.addWidget(self.qr_status_label)
|
||||
|
||||
back = QPushButton("Retour")
|
||||
back.setFont(QFont("", 14))
|
||||
back.setStyleSheet(BACK_BTN_STYLE)
|
||||
back.clicked.connect(self._show_modes)
|
||||
layout.addWidget(back, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
layout.addStretch()
|
||||
return page
|
||||
|
||||
# ─── Page 4 : Email ───
|
||||
|
||||
def _build_email_instructions(self):
|
||||
def _build_email_page(self):
|
||||
page = QWidget()
|
||||
layout = QVBoxLayout(page)
|
||||
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.setSpacing(25)
|
||||
layout.setSpacing(20)
|
||||
|
||||
layout.addLayout(self._make_page_header())
|
||||
|
||||
instruction = QLabel("Envoyez vos photos par email\nà l'adresse suivante :")
|
||||
instruction.setFont(QFont("", 24))
|
||||
instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(instruction)
|
||||
|
||||
# Adresse email mise en évidence
|
||||
self.email_address_label = QLabel(EMAIL_ADDRESS)
|
||||
layout.addStretch()
|
||||
|
||||
self.email_address_label = QLabel(self.config["email_address"])
|
||||
self.email_address_label.setFont(QFont("", 28, QFont.Weight.Bold))
|
||||
self.email_address_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.email_address_label.setStyleSheet(HIGHLIGHT_STYLE)
|
||||
self.email_address_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
|
||||
layout.addWidget(self.email_address_label)
|
||||
|
||||
hint = QLabel("Joignez vos photos en pièce jointe\net envoyez depuis votre téléphone")
|
||||
@@ -315,22 +334,16 @@ class HomeScreen(QWidget):
|
||||
hint.setStyleSheet("color: #666;")
|
||||
layout.addWidget(hint)
|
||||
|
||||
# Status réception
|
||||
self.email_status_label = QLabel("En attente de réception...")
|
||||
self.email_status_label.setFont(QFont("", 16))
|
||||
self.email_status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.email_status_label.setStyleSheet(INFO_STYLE)
|
||||
layout.addWidget(self.email_status_label)
|
||||
|
||||
back = QPushButton("Retour")
|
||||
back.setFont(QFont("", 14))
|
||||
back.setStyleSheet(BACK_BTN_STYLE)
|
||||
back.clicked.connect(self._show_modes)
|
||||
layout.addWidget(back, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
layout.addStretch()
|
||||
return page
|
||||
|
||||
# ─── Navigation entre pages ───
|
||||
# ─── Navigation ───
|
||||
|
||||
def _show_modes(self):
|
||||
self.stack.setCurrentIndex(0)
|
||||
@@ -340,15 +353,32 @@ class HomeScreen(QWidget):
|
||||
self.stack.setCurrentIndex(1)
|
||||
|
||||
def _show_wifi(self):
|
||||
self._refresh_config_labels()
|
||||
self.stack.setCurrentIndex(2)
|
||||
|
||||
def _show_qr(self):
|
||||
self._refresh_config_labels()
|
||||
self._generate_qr()
|
||||
self.stack.setCurrentIndex(3)
|
||||
|
||||
def _show_email(self):
|
||||
self._refresh_config_labels()
|
||||
self.stack.setCurrentIndex(4)
|
||||
|
||||
# ─── Config ───
|
||||
|
||||
def _open_config(self):
|
||||
if ConfigDialog.open_config(self):
|
||||
self.config = load_config()
|
||||
self._refresh_config_labels()
|
||||
|
||||
def _refresh_config_labels(self):
|
||||
"""Met à jour les labels avec la config actuelle."""
|
||||
self.config = load_config()
|
||||
self.wifi_name_label.setText(f"Nom du réseau : {self.config['wifi_ap_name']}")
|
||||
self.wifi_pass_label.setText(f"Mot de passe : {self.config['wifi_ap_password']}")
|
||||
self.email_address_label.setText(self.config["email_address"])
|
||||
|
||||
# ─── USB ───
|
||||
|
||||
def _setup_usb_watcher(self):
|
||||
@@ -395,13 +425,12 @@ class HomeScreen(QWidget):
|
||||
import qrcode
|
||||
import io
|
||||
|
||||
upload_url = f"http://192.168.4.1/upload"
|
||||
upload_url = self.config["upload_url"]
|
||||
qr = qrcode.QRCode(version=1, box_size=8, border=2)
|
||||
qr.add_data(upload_url)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
# PIL Image -> QPixmap
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
|
||||
Reference in New Issue
Block a user