Impostazioni a schede; voce tolta dal pannello Customise

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Fable 5.1 committed 2026-09-24 11:08:29 +02:00
1 parent baeab8936b
commit 64f3474d92
2 files changed
+27 -35

No files matched your search

+25 -13
View File
@@ -5,7 +5,7 @@ import threading
from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDialog, QFormLayout, QFrame, QHBoxLayout, QLabel, QLineEdit, from PyQt6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDialog, QFormLayout, QFrame, QHBoxLayout, QLabel, QLineEdit,
QPushButton, QScrollArea, QStackedWidget, QVBoxLayout, QWidget, QDoubleSpinBox) QPushButton, QScrollArea, QStackedWidget, QTabWidget, QVBoxLayout, QWidget, QDoubleSpinBox)
from .engines.claude_code import check_claude_code from .engines.claude_code import check_claude_code
from .engines.openai_compat import list_models from .engines.openai_compat import list_models
@@ -13,7 +13,10 @@ from .settings import Settings
from .tts import KOKORO_VOICES, SystemVoice from .tts import KOKORO_VOICES, SystemVoice
STYLE = """ STYLE = """
QDialog, QScrollArea, QScrollArea > QWidget > QWidget { background: #030a10; color: #cfe8ff; } QDialog, QScrollArea, QScrollArea > QWidget > QWidget, QTabWidget::pane { background: #030a10; color: #cfe8ff; }
QTabWidget::pane { border: 1px solid #12354a; border-radius: 4px; }
QTabBar::tab { background: #05202c; color: #9fdfff; padding: 7px 16px; border: 1px solid #12354a; border-bottom: none; border-top-left-radius: 4px; border-top-right-radius: 4px; font-family: 'Menlo'; font-size: 13px; margin-right: 2px; }
QTabBar::tab:selected { background: #0a4a66; color: #ffffff; }
QLabel { color: #8fb8d8; font-family: 'Menlo'; font-size: 14px; } QLabel { color: #8fb8d8; font-family: 'Menlo'; font-size: 14px; }
QLineEdit, QComboBox, QDoubleSpinBox { background: #000d12; color: #e6f4ff; border: 1px solid #12354a; border-radius: 3px; padding: 4px 6px; font-family: 'Menlo'; font-size: 14px; } QLineEdit, QComboBox, QDoubleSpinBox { background: #000d12; color: #e6f4ff; border: 1px solid #12354a; border-radius: 3px; padding: 4px 6px; font-family: 'Menlo'; font-size: 14px; }
QLineEdit:focus, QComboBox:focus { border: 1px solid #3fd0ff; } QLineEdit:focus, QComboBox:focus { border: 1px solid #3fd0ff; }
@@ -51,16 +54,26 @@ class SettingsDialog(QDialog):
self.setStyleSheet(STYLE) self.setStyleSheet(STYLE)
self.setMinimumWidth(720) self.setMinimumWidth(720)
s = settings s = settings
# Contenuto scorrevole; i pulsanti Salva/Annulla restano fissi in basso. # Schede: Motore, Voce, Messaggistica, Monitor. Salva/Annulla fissi in basso.
content = QWidget() self.tabs = QTabWidget()
root = QVBoxLayout(content) def page(title: str) -> QVBoxLayout:
w = QWidget(); lay = QVBoxLayout(w); lay.setContentsMargins(12, 12, 12, 12); lay.setSpacing(10)
sc = QScrollArea(); sc.setWidgetResizable(True); sc.setWidget(w); sc.setFrameShape(QFrame.Shape.NoFrame)
self.tabs.addTab(sc, title)
lay.addStretch(1)
return lay
pg_motore, pg_voce, pg_msg, pg_mon = page("Motore"), page("Voce e avatar"), page("Messaggistica"), page("Monitor")
def add(lay, item): # inserisce prima dello stretch finale
if isinstance(item, QWidget): lay.insertWidget(lay.count() - 1, item)
else: lay.insertLayout(lay.count() - 1, item)
root = pg_motore
form = QFormLayout() form = QFormLayout()
self.provider = _combo(PROVIDERS, s.get("provider")) self.provider = _combo(PROVIDERS, s.get("provider"))
form.addRow("Motore", self.provider) form.addRow("Motore", self.provider)
self.effort = _combo(EFFORTS, s.get("effort")) self.effort = _combo(EFFORTS, s.get("effort"))
form.addRow("Profondità di ragionamento (Claude e Claude Code)", self.effort) form.addRow("Profondità di ragionamento (Claude e Claude Code)", self.effort)
root.addLayout(form) add(pg_motore, form)
self.stack = QStackedWidget() self.stack = QStackedWidget()
# Anthropic # Anthropic
@@ -96,7 +109,7 @@ class SettingsDialog(QDialog):
self.cc_path = QLineEdit(s.get("claudecode_path")); self.cc_path.setPlaceholderText("vuoto = automatico") self.cc_path = QLineEdit(s.get("claudecode_path")); self.cc_path.setPlaceholderText("vuoto = automatico")
f.addRow("Percorso del comando claude", self.cc_path) f.addRow("Percorso del comando claude", self.cc_path)
self.stack.addWidget(w) self.stack.addWidget(w)
root.addWidget(self.stack) add(pg_motore, self.stack)
self.provider.currentIndexChanged.connect(self.stack.setCurrentIndex) self.provider.currentIndexChanged.connect(self.stack.setCurrentIndex)
self.stack.setCurrentIndex(self.provider.currentIndex()) self.stack.setCurrentIndex(self.provider.currentIndex())
@@ -148,7 +161,7 @@ class SettingsDialog(QDialog):
form2.addRow("Avatar 3D (file in avatar3d/models)", self.avatar_model) form2.addRow("Avatar 3D (file in avatar3d/models)", self.avatar_model)
self.vad = QDoubleSpinBox(); self.vad.setRange(0.02, 0.5); self.vad.setSingleStep(0.01); self.vad.setValue(float(s.get("vad_threshold", 0.08))) self.vad = QDoubleSpinBox(); self.vad.setRange(0.02, 0.5); self.vad.setSingleStep(0.01); self.vad.setValue(float(s.get("vad_threshold", 0.08)))
form2.addRow("Sensibilità microfono (più basso = più sensibile)", self.vad) form2.addRow("Sensibilità microfono (più basso = più sensibile)", self.vad)
root.addLayout(form2) add(pg_voce, form2)
# ── Telegram ────────────────────────────────────────────────────── # ── Telegram ──────────────────────────────────────────────────────
form3 = QFormLayout() form3 = QFormLayout()
@@ -171,7 +184,7 @@ class SettingsDialog(QDialog):
self.tg_qr_label = QLabel(); self.tg_qr_label.setFixedSize(220, 220); self.tg_qr_label.setScaledContents(True); row.addWidget(self.tg_qr_label); row.addStretch() self.tg_qr_label = QLabel(); self.tg_qr_label.setFixedSize(220, 220); self.tg_qr_label.setScaledContents(True); row.addWidget(self.tg_qr_label); row.addStretch()
form3.addRow("Alternativa", row) form3.addRow("Alternativa", row)
self.tg_hint = QLabel("…"); self.tg_hint.setWordWrap(True); form3.addRow("", self.tg_hint) self.tg_hint = QLabel("…"); self.tg_hint.setWordWrap(True); form3.addRow("", self.tg_hint)
root.addLayout(form3) add(pg_msg, form3)
threading.Thread(target=lambda: self._async.emit("tg", self._tg_status()), daemon=True).start() threading.Thread(target=lambda: self._async.emit("tg", self._tg_status()), daemon=True).start()
# ── WhatsApp (dispositivo collegato, Baileys) ───────────────────── # ── WhatsApp (dispositivo collegato, Baileys) ─────────────────────
@@ -188,7 +201,7 @@ class SettingsDialog(QDialog):
self.wa_qr_label = QLabel(); self.wa_qr_label.setFixedSize(220, 220); self.wa_qr_label.setScaledContents(True); row.addWidget(self.wa_qr_label) self.wa_qr_label = QLabel(); self.wa_qr_label.setFixedSize(220, 220); self.wa_qr_label.setScaledContents(True); row.addWidget(self.wa_qr_label)
self.wa_hint = QLabel("…"); self.wa_hint.setWordWrap(True); row.addWidget(self.wa_hint, 1) self.wa_hint = QLabel("…"); self.wa_hint.setWordWrap(True); row.addWidget(self.wa_hint, 1)
form4.addRow("", row) form4.addRow("", row)
root.addLayout(form4) add(pg_msg, form4)
threading.Thread(target=lambda: self._async.emit("wa", (self._wa_status(), None)), daemon=True).start() threading.Thread(target=lambda: self._async.emit("wa", (self._wa_status(), None)), daemon=True).start()
# ── Monitor avvisi ──────────────────────────────────────────────── # ── Monitor avvisi ────────────────────────────────────────────────
@@ -204,14 +217,13 @@ class SettingsDialog(QDialog):
form5.addRow("Cosa merita un avviso", self.mon_rules) form5.addRow("Cosa merita un avviso", self.mon_rules)
self.mon_excl = QLineEdit(s.get("monitor_escludi") or ""); self.mon_excl.setPlaceholderText("es. newsletter, offerta, gruppo Calcetto, Amazon — parole separate da virgola, cercate in mittente, chat e testo") self.mon_excl = QLineEdit(s.get("monitor_escludi") or ""); self.mon_excl.setPlaceholderText("es. newsletter, offerta, gruppo Calcetto, Amazon — parole separate da virgola, cercate in mittente, chat e testo")
form5.addRow("Escludi dagli avvisi", self.mon_excl) form5.addRow("Escludi dagli avvisi", self.mon_excl)
root.addLayout(form5) add(pg_mon, form5)
btns = QHBoxLayout(); btns.addStretch() btns = QHBoxLayout(); btns.addStretch()
cancel = QPushButton("Annulla"); cancel.clicked.connect(self.reject); btns.addWidget(cancel) cancel = QPushButton("Annulla"); cancel.clicked.connect(self.reject); btns.addWidget(cancel)
save = QPushButton("Salva"); save.setObjectName("primary"); save.clicked.connect(self._save); btns.addWidget(save) save = QPushButton("Salva"); save.setObjectName("primary"); save.clicked.connect(self._save); btns.addWidget(save)
scroll = QScrollArea(); scroll.setWidgetResizable(True); scroll.setWidget(content); scroll.setFrameShape(QFrame.Shape.NoFrame)
outer = QVBoxLayout(self); outer.setContentsMargins(10, 10, 10, 10) outer = QVBoxLayout(self); outer.setContentsMargins(10, 10, 10, 10)
outer.addWidget(scroll, 1) outer.addWidget(self.tabs, 1)
outer.addLayout(btns) outer.addLayout(btns)
screen = QApplication.primaryScreen().availableGeometry() if QApplication.primaryScreen() else None screen = QApplication.primaryScreen().availableGeometry() if QApplication.primaryScreen() else None
h = int(screen.height() * 0.85) if screen else 800 h = int(screen.height() * 0.85) if screen else 800
+2 -22
View File
@@ -1645,29 +1645,9 @@ class CustomizeOverlay(QWidget):
self._user_input.setStyleSheet(_fs) self._user_input.setStyleSheet(_fs)
lay.addWidget(self._user_input) lay.addWidget(self._user_input)
# ── Assistant voice — Gemini prebuilt voices ───────────────────────── # AvatarPy: la voce si sceglie in «Motore e Voce»; qui resta solo il valore corrente.
# Names are language-neutral proper nouns, so the row reads the same in self._sel_voice = voice or ""
# every locale. Selecting one and applying rebuilds the Live session.
from memory.config_manager import AVAILABLE_VOICES, DEFAULT_VOICE
lay.addSpacing(4)
lay.addWidget(_lbl("ASSISTANT VOICE", 11, color=C.TEXT_DIM,
align=Qt.AlignmentFlag.AlignLeft))
self._sel_voice = (voice or DEFAULT_VOICE)
if self._sel_voice not in AVAILABLE_VOICES:
self._sel_voice = DEFAULT_VOICE
self._voice_btns: dict[str, QPushButton] = {} self._voice_btns: dict[str, QPushButton] = {}
voice_row = QHBoxLayout(); voice_row.setSpacing(4)
for _v in AVAILABLE_VOICES:
b = QPushButton(_v)
b.setCheckable(True)
b.setFixedHeight(28)
b.setFont(QFont("Menlo", 11, QFont.Weight.Bold))
b.setCursor(Qt.CursorShape.PointingHandCursor)
b.clicked.connect(lambda _=False, name=_v: self._on_voice_pick(name))
self._voice_btns[_v] = b
voice_row.addWidget(b)
lay.addLayout(voice_row)
self._refresh_voice_btns()
# ── UI colour — colour wheel ───────────────────────────────────────── # ── UI colour — colour wheel ─────────────────────────────────────────
lay.addSpacing(4) lay.addSpacing(4)