import json
from datetime import date
from qgis.PyQt.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout,
QLabel, QLineEdit, QPushButton, QMessageBox, QComboBox,
QDateEdit, QSpinBox, QCheckBox, QScrollArea, QWidget,
QListWidget, QListWidgetItem, QInputDialog, QSizePolicy,
QFrame, QGroupBox
)
from qgis.PyQt.QtCore import Qt, QDate
from qgis.PyQt.QtGui import QFont, QColor
from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject
from qgis.utils import iface
from .map_point_tool import PointCaptureTool
# ---------------------------------------------------------------------------
# Widgets utilitaires
# ---------------------------------------------------------------------------
class ComboWithAdd(QWidget):
def __init__(self, add_callback, parent=None):
super().__init__(parent)
self._add_callback = add_callback
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self.combo = QComboBox()
self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.btn_add = QPushButton("+")
self.btn_add.setFixedWidth(30)
self.btn_add.setToolTip("Ajouter un nouvel élément")
self.btn_add.clicked.connect(lambda: self._add_callback(self))
layout.addWidget(self.combo)
layout.addWidget(self.btn_add)
def current_data(self):
return self.combo.currentData()
def current_text(self):
return self.combo.currentText()
def populate(self, items, placeholder=None):
self.combo.clear()
if placeholder:
self.combo.addItem(placeholder, None)
for code, label in items:
self.combo.addItem(label, code)
def add_item(self, code, label):
self.combo.addItem(label, code)
self.combo.setCurrentIndex(self.combo.count() - 1)
def set_by_text(self, text):
idx = self.combo.findText(text)
if idx >= 0:
self.combo.setCurrentIndex(idx)
def set_by_data(self, data):
idx = self.combo.findData(data)
if idx >= 0:
self.combo.setCurrentIndex(idx)
class AnimateursWidget(QWidget):
def __init__(self, db, parent=None):
super().__init__(parent)
self.db = db
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self.list_widget = QListWidget()
self.list_widget.setMaximumHeight(90)
layout.addWidget(self.list_widget)
btn_layout = QHBoxLayout()
self.combo = QComboBox()
self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
btn_add = QPushButton("Ajouter")
btn_add.clicked.connect(self._add_existing)
btn_new = QPushButton("+ Nouveau")
btn_new.clicked.connect(self._add_new)
btn_remove = QPushButton("Retirer")
btn_remove.clicked.connect(self._remove_selected)
btn_layout.addWidget(self.combo)
btn_layout.addWidget(btn_add)
btn_layout.addWidget(btn_new)
btn_layout.addWidget(btn_remove)
layout.addLayout(btn_layout)
self.load_animateurs()
def load_animateurs(self):
self.combo.clear()
for code, nom in self.db.get_animateurs():
self.combo.addItem(nom, code)
def _add_existing(self):
code = self.combo.currentData()
nom = self.combo.currentText()
if code is None:
return
for i in range(self.list_widget.count()):
if self.list_widget.item(i).data(Qt.UserRole) == code:
return
item = QListWidgetItem(nom)
item.setData(Qt.UserRole, code)
self.list_widget.addItem(item)
def _add_new(self):
nom, ok = QInputDialog.getText(self, "Nouvel animateur", "Nom :")
if ok and nom.strip():
try:
code, label = self.db.add_animateur(nom.strip())
self.combo.addItem(label, code)
item = QListWidgetItem(label)
item.setData(Qt.UserRole, code)
self.list_widget.addItem(item)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _remove_selected(self):
for item in self.list_widget.selectedItems():
self.list_widget.takeItem(self.list_widget.row(item))
def get_value(self):
result = []
for i in range(self.list_widget.count()):
item = self.list_widget.item(i)
result.append({"code": item.data(Qt.UserRole), "nom": item.text()})
return json.dumps(result, ensure_ascii=False) if result else None
def set_value(self, json_str):
self.list_widget.clear()
if not json_str:
return
try:
data = json.loads(json_str) if isinstance(json_str, str) else json_str
for entry in data:
item = QListWidgetItem(entry.get("nom", ""))
item.setData(Qt.UserRole, entry.get("code"))
self.list_widget.addItem(item)
except Exception:
pass
# ---------------------------------------------------------------------------
# Dialogue principal
# ---------------------------------------------------------------------------
class SaisieDialog(QDialog):
def __init__(self, db, parent=None):
super().__init__(parent)
self.db = db
self._etab_map = {} # code -> (nom, commune)
self._edit_mode = False # True = on édite une animation existante
self._edit_code = None # code_animation en cours d'édition
self._pending_geom = None # (x, y, crs) en attente pour ajout lieu/etab
self._pending_geom_type = None # 'lieu' ou 'etab'
self._point_tool = None
self.setWindowTitle("Animation – Saisie / Édition")
self.setMinimumWidth(720)
self.setMinimumHeight(820)
self._build_ui()
self._load_reference_data()
# -----------------------------------------------------------------------
# Construction UI
# -----------------------------------------------------------------------
def _build_ui(self):
main_layout = QVBoxLayout(self)
main_layout.setSpacing(6)
# --- Bandeau titre ---
self.title_label = QLabel("
Nouvelle animation
")
self.title_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(self.title_label)
# --- Sélecteur d'animation existante ---
grp_sel = QGroupBox("Charger / modifier une animation existante")
sel_layout = QHBoxLayout(grp_sel)
self.anim_combo = QComboBox()
self.anim_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.anim_combo.setPlaceholderText("── Nouvelle saisie ──")
self.anim_combo.addItem("── Nouvelle saisie ──", None)
self.anim_combo.currentIndexChanged.connect(self._on_anim_selected)
sel_layout.addWidget(QLabel("Animation :"))
sel_layout.addWidget(self.anim_combo)
btn_refresh = QPushButton("🔄")
btn_refresh.setFixedWidth(32)
btn_refresh.setToolTip("Rafraîchir la liste")
btn_refresh.clicked.connect(self._reload_animations_list)
sel_layout.addWidget(btn_refresh)
main_layout.addWidget(grp_sel)
# --- Zone scrollable du formulaire ---
scroll = QScrollArea()
scroll.setWidgetResizable(True)
container = QWidget()
self.fl = QFormLayout(container)
self.fl.setLabelAlignment(Qt.AlignRight)
self.fl.setSpacing(8)
scroll.setWidget(container)
main_layout.addWidget(scroll)
fl = self.fl
# ---- Date & Durée ----
self._section(fl, "Date et durée")
self.date_edit = QDateEdit(QDate.currentDate())
self.date_edit.setCalendarPopup(True)
self.date_edit.setDisplayFormat("dd/MM/yyyy")
fl.addRow("Date *:", self.date_edit)
dur_w = QWidget()
dur_l = QHBoxLayout(dur_w)
dur_l.setContentsMargins(0, 0, 0, 0)
self.duree_h = QSpinBox()
self.duree_h.setRange(0, 24)
self.duree_h.setSuffix(" h")
self.duree_min = QSpinBox()
self.duree_min.setRange(0, 59)
self.duree_min.setSuffix(" min")
dur_l.addWidget(self.duree_h)
dur_l.addWidget(self.duree_min)
dur_l.addStretch()
fl.addRow("Durée :", dur_w)
self.prepa_spin = QSpinBox()
self.prepa_spin.setRange(0, 9999)
self.prepa_spin.setSuffix(" min")
for w in (self.duree_h, self.duree_min, self.prepa_spin):
w.valueChanged.connect(self._update_temps_total)
fl.addRow("Prépa / déplacement :", self.prepa_spin)
self.temps_total_label = QLabel("0 min")
fl.addRow("Temps total (calculé) :", self.temps_total_label)
# ---- Animateurs ----
self._sep(fl)
self._section(fl, "Animateurs")
self.animateurs_widget = AnimateursWidget(self.db)
fl.addRow("Animateurs :", self.animateurs_widget)
# ---- Groupe ----
self._sep(fl)
self._section(fl, "Groupe")
self.type_groupe_combo = ComboWithAdd(self._add_type_groupe)
fl.addRow("Type de groupe :", self.type_groupe_combo)
self.precisions_groupe_edit = QLineEdit()
fl.addRow("Précisions groupe :", self.precisions_groupe_edit)
# ---- Établissement ----
self._sep(fl)
self._section(fl, "Établissement / Provenance")
self.etab_combo = ComboWithAdd(self._add_etablissement)
self.etab_combo.combo.currentIndexChanged.connect(self._on_etab_changed)
fl.addRow("Établissement :", self.etab_combo)
self.commune_label = QLabel("")
self.commune_label.setStyleSheet("color:#555; font-style:italic;")
fl.addRow("Commune (auto) :", self.commune_label)
# ---- Participants ----
self._sep(fl)
self._section(fl, "Participants")
self.enfants_spin = QSpinBox()
self.enfants_spin.setRange(0, 9999)
self.enfants_spin.valueChanged.connect(self._update_total_pers)
fl.addRow("Enfants :", self.enfants_spin)
self.adultes_spin = QSpinBox()
self.adultes_spin.setRange(0, 9999)
self.adultes_spin.valueChanged.connect(self._update_total_pers)
fl.addRow("Adultes :", self.adultes_spin)
self.total_pers_label = QLabel("0")
fl.addRow("Total (calculé) :", self.total_pers_label)
# ---- Lieu ----
self._sep(fl)
self._section(fl, "Lieu")
self.lieux_combo = ComboWithAdd(self._add_lieu)
fl.addRow("Lieu :", self.lieux_combo)
self.precisions_lieux_edit = QLineEdit()
fl.addRow("Précisions lieu :", self.precisions_lieux_edit)
self.accueil_pin_check = QCheckBox("Oui")
fl.addRow("Accueil PIN :", self.accueil_pin_check)
# ---- Thème ----
self._sep(fl)
self._section(fl, "Thème")
self.theme_combo = ComboWithAdd(self._add_theme)
fl.addRow("Thème :", self.theme_combo)
self.theme_detaille_edit = QLineEdit()
fl.addRow("Thème détaillé :", self.theme_detaille_edit)
# ---- Statuts ----
self._sep(fl)
self._section(fl, "Statuts")
self.payant_check = QCheckBox("Oui")
fl.addRow("Payant :", self.payant_check)
self.annul_combo = ComboWithAdd(self._add_annulation)
fl.addRow("Annulation :", self.annul_combo)
self.dossier_combo = ComboWithAdd(self._add_dossier)
fl.addRow("Dossier enseignant :", self.dossier_combo)
self.tiers_check = QCheckBox("Oui")
self.tiers_check.stateChanged.connect(self._on_tiers_changed)
fl.addRow("Réalisé par tiers :", self.tiers_check)
self.detail_tiers_edit = QLineEdit()
self.detail_tiers_edit.setEnabled(False)
fl.addRow("Détail tiers :", self.detail_tiers_edit)
# ---- Remarques ----
self._sep(fl)
self.remarques_edit = QLineEdit()
fl.addRow("Remarques :", self.remarques_edit)
# --- Boutons d'action ---
btn_layout = QHBoxLayout()
btn_cancel = QPushButton("Fermer")
btn_cancel.clicked.connect(self.reject)
self.btn_new_form = QPushButton("✚ Nouveau")
self.btn_new_form.setToolTip("Réinitialiser pour une nouvelle saisie")
self.btn_new_form.clicked.connect(self._new_form)
self.btn_save_new = QPushButton("Enregistrer et nouveau")
self.btn_save_new.clicked.connect(self._save_and_new)
self.btn_save = QPushButton("Enregistrer")
self.btn_save.setDefault(True)
self.btn_save.clicked.connect(self._save)
btn_layout.addWidget(btn_cancel)
btn_layout.addWidget(self.btn_new_form)
btn_layout.addStretch()
btn_layout.addWidget(self.btn_save_new)
btn_layout.addWidget(self.btn_save)
main_layout.addLayout(btn_layout)
def _section(self, fl, title):
lbl = QLabel(f"{title}")
fl.addRow(lbl)
def _sep(self, fl):
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setStyleSheet("color:#ccc;")
fl.addRow(line)
# -----------------------------------------------------------------------
# Chargement données de référence
# -----------------------------------------------------------------------
def _load_reference_data(self):
try:
self.type_groupe_combo.populate(self.db.get_types_groupe(), "-- Sélectionner --")
etabs = self.db.get_etablissements()
self._etab_map = {c: (n, com) for c, n, com in etabs}
self.etab_combo.populate(
[(c, f"{n} ({com})" if com else n) for c, n, com in etabs],
"-- Sélectionner --"
)
self.lieux_combo.populate(self.db.get_lieux(), "-- Sélectionner --")
self.theme_combo.populate(self.db.get_themes(), "-- Sélectionner --")
self.annul_combo.populate(self.db.get_codes_annulation(), "Non")
self._set_default(self.annul_combo, "Non")
self.dossier_combo.populate(self.db.get_type_dossier_ens(), "Non")
self._set_default(self.dossier_combo, "Non")
self._reload_animations_list()
except Exception as e:
QMessageBox.critical(self, "Erreur chargement", str(e))
def _set_default(self, combo_widget, text):
idx = combo_widget.combo.findText(text)
if idx >= 0:
combo_widget.combo.setCurrentIndex(idx)
def _reload_animations_list(self):
self.anim_combo.blockSignals(True)
self.anim_combo.clear()
self.anim_combo.addItem("── Nouvelle saisie ──", None)
try:
rows = self.db.get_all_animations()
for code, date_anim, lieux, theme in rows:
date_str = date_anim.strftime("%d/%m/%Y") if date_anim else "?"
lieux_str = lieux or "Lieu ?"
theme_str = theme or "Thème ?"
label = f"{date_str} | {lieux_str} | {theme_str} [#{code}]"
self.anim_combo.addItem(label, code)
except Exception as e:
QMessageBox.warning(self, "Erreur", f"Impossible de charger les animations : {e}")
self.anim_combo.blockSignals(False)
# -----------------------------------------------------------------------
# Événements
# -----------------------------------------------------------------------
def _on_anim_selected(self, idx):
code = self.anim_combo.itemData(idx)
if code is None:
self._new_form()
return
try:
data = self.db.get_animation_by_id(code)
if data:
self._edit_mode = True
self._edit_code = code
self.title_label.setText(f"Édition animation #{code}
")
self.btn_save.setText("Mettre à jour")
self.btn_save_new.setVisible(False)
self._populate_form(data)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _populate_form(self, data):
"""Remplit le formulaire avec les données d'une animation existante."""
if data.get('date_anim'):
d = data['date_anim']
self.date_edit.setDate(QDate(d.year, d.month, d.day))
duree = data.get('duree_anim', '0h00') or '0h00'
try:
if 'h' in duree:
h, m = duree.split('h')
self.duree_h.setValue(int(h))
self.duree_min.setValue(int(m) if m else 0)
except Exception:
pass
self.prepa_spin.setValue(data.get('prepa_deplacemt') or 0)
self.animateurs_widget.set_value(data.get('animateurs'))
self.type_groupe_combo.set_by_data(data.get('code_groupe'))
self.precisions_groupe_edit.setText(data.get('precisions_type_de_groupe') or '')
# Établissement : chercher par nom
nom_etab = data.get('nom_etablissement') or ''
for code, (nom, com) in self._etab_map.items():
if nom == nom_etab:
self.etab_combo.set_by_data(code)
break
self.enfants_spin.setValue(data.get('nbre_pers_enfants') or 0)
self.adultes_spin.setValue(data.get('nbre_pers_adultes') or 0)
self.lieux_combo.set_by_text(data.get('lieux') or '')
self.precisions_lieux_edit.setText(data.get('precisions_lieux_anim') or '')
self.accueil_pin_check.setChecked(bool(data.get('accueil_pin')))
self.theme_detaille_edit.setText(data.get('theme_detaille') or '')
self.theme_combo.set_by_data(data.get('code_type_anim'))
self.payant_check.setChecked(bool(data.get('payant')))
self.annul_combo.set_by_text(data.get('type_annul') or 'Non')
self.remarques_edit.setText(data.get('remarques') or '')
self.dossier_combo.set_by_text(data.get('type_dossier_ens') or 'Non')
realise = bool(data.get('realise_par_tiers'))
self.tiers_check.setChecked(realise)
self.detail_tiers_edit.setText(data.get('detail_tiers') or '')
self.detail_tiers_edit.setEnabled(realise)
def _new_form(self):
self._edit_mode = False
self._edit_code = None
self.title_label.setText("Nouvelle animation
")
self.btn_save.setText("Enregistrer")
self.btn_save_new.setVisible(True)
self.anim_combo.blockSignals(True)
self.anim_combo.setCurrentIndex(0)
self.anim_combo.blockSignals(False)
self._reset_form()
def _on_etab_changed(self, idx):
code = self.etab_combo.combo.itemData(idx)
if code and code in self._etab_map:
self.commune_label.setText(self._etab_map[code][1] or "")
else:
self.commune_label.setText("")
def _on_tiers_changed(self, state):
self.detail_tiers_edit.setEnabled(state == Qt.Checked)
def _update_temps_total(self):
total = self.duree_h.value() * 60 + self.duree_min.value() + self.prepa_spin.value()
self.temps_total_label.setText(f"{total} min")
def _update_total_pers(self):
self.total_pers_label.setText(str(self.enfants_spin.value() + self.adultes_spin.value()))
# -----------------------------------------------------------------------
# Capture géométrie sur carte
# -----------------------------------------------------------------------
def _start_point_capture(self, geom_type, on_captured_callback):
"""
Lance l'outil de clic sur la carte. geom_type = 'lieu' ou 'etab'.
Après le clic, appelle on_captured_callback(wkt, srid).
"""
canvas = iface.mapCanvas()
if not canvas:
QMessageBox.warning(self, "Erreur", "Impossible d'accéder à la carte QGIS.")
return
prev_tool = canvas.mapTool()
tool = PointCaptureTool(canvas, prev_tool)
def on_point(x, y, crs):
# Convertir en WGS84 (4326) si nécessaire
wgs84 = QgsCoordinateReferenceSystem("EPSG:4326")
if crs != wgs84:
transform = QgsCoordinateTransform(crs, wgs84, QgsProject.instance())
from qgis.core import QgsPointXY
pt = transform.transform(x, y)
x, y = pt.x(), pt.y()
wkt = f"POINT({x} {y})"
on_captured_callback(wkt, 4326)
self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive)
self.activateWindow()
tool.pointCaptured.connect(on_point)
self._point_tool = tool
# Minimiser le dialogue et activer l'outil
self.showMinimized()
canvas.setMapTool(tool)
# -----------------------------------------------------------------------
# Callbacks ajout nouveaux éléments
# -----------------------------------------------------------------------
def _add_type_groupe(self, widget):
QMessageBox.information(self, "Info",
"L'ajout d'un type de groupe nécessite un code entier.\n"
"Veuillez contacter l'administrateur de la base.")
def _add_lieu(self, widget):
val, ok = QInputDialog.getText(self, "Nouveau lieu", "Nom du lieu :")
if not ok or not val.strip():
return
nom = val.strip()
reply = QMessageBox.question(self, "Géométrie",
"Souhaitez-vous localiser ce lieu sur la carte ?",
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
def on_geom(wkt, srid):
try:
code, label = self.db.add_lieux(nom, geom_wkt=wkt, srid=srid)
widget.add_item(code, label)
QMessageBox.information(self, "Succès", f"Lieu « {label} » ajouté avec géométrie.")
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
self._start_point_capture('lieu', on_geom)
else:
try:
code, label = self.db.add_lieux(nom)
widget.add_item(code, label)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _add_theme(self, widget):
val, ok = QInputDialog.getText(self, "Nouveau thème", "Libellé :")
if ok and val.strip():
try:
code, label = self.db.add_theme(val.strip())
widget.add_item(code, label)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _add_annulation(self, widget):
val, ok = QInputDialog.getText(self, "Nouveau type d'annulation", "Libellé :")
if ok and val.strip():
try:
code, label = self.db.add_annulation(val.strip())
widget.add_item(code, label)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _add_dossier(self, widget):
val, ok = QInputDialog.getText(self, "Nouveau type de dossier", "Libellé :")
if ok and val.strip():
try:
code, label = self.db.add_type_dossier(val.strip())
widget.add_item(code, label)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _add_etablissement(self, widget):
nom, ok = QInputDialog.getText(self, "Nouvel établissement", "Nom :")
if not ok or not nom.strip():
return
commune, ok2 = QInputDialog.getText(self, "Nouvel établissement", "Commune :")
if not ok2:
return
nom = nom.strip()
commune = commune.strip()
reply = QMessageBox.question(self, "Géométrie",
"Souhaitez-vous localiser cet établissement sur la carte ?",
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
def on_geom(wkt, srid):
try:
code, label, com = self.db.add_etablissement(nom, commune, geom_wkt=wkt, srid=srid)
self._etab_map[code] = (label, com)
display = f"{label} ({com})" if com else label
widget.add_item(code, display)
QMessageBox.information(self, "Succès", f"Établissement « {label} » ajouté avec géométrie.")
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
self._start_point_capture('etab', on_geom)
else:
try:
code, label, com = self.db.add_etablissement(nom, commune)
self._etab_map[code] = (label, com)
display = f"{label} ({com})" if com else label
widget.add_item(code, display)
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
# -----------------------------------------------------------------------
# Collecte, validation, enregistrement
# -----------------------------------------------------------------------
def _collect_data(self):
duree_str = f"{self.duree_h.value()}h{self.duree_min.value():02d}"
duree_min_total = self.duree_h.value() * 60 + self.duree_min.value()
temps_total = duree_min_total + self.prepa_spin.value() or None
etab_code = self.etab_combo.current_data()
nom_etab, commune_prov = (None, None)
if etab_code and etab_code in self._etab_map:
nom_etab, commune_prov = self._etab_map[etab_code]
lieux_txt = self.lieux_combo.current_text() if self.lieux_combo.current_data() else None
type_annul = self.annul_combo.current_text() if self.annul_combo.current_data() else None
type_dossier = self.dossier_combo.current_text() if self.dossier_combo.current_data() else None
realise_tiers = self.tiers_check.isChecked()
return {
"date_anim": self.date_edit.date().toPyDate(),
"duree_anim": duree_str,
"animateurs": self.animateurs_widget.get_value(),
"prepa_deplacemt": self.prepa_spin.value() or None,
"temps_total": temps_total,
"code_groupe": self.type_groupe_combo.current_data(),
"precisions_type_de_groupe": self.precisions_groupe_edit.text().strip() or None,
"commune_provenance": commune_prov,
"nom_etablissement": nom_etab,
"nbre_pers_enfants": self.enfants_spin.value() or None,
"nbre_pers_adultes": self.adultes_spin.value() or None,
"nbre_pers_total": (self.enfants_spin.value() + self.adultes_spin.value()) or None,
"lieux": lieux_txt,
"precisions_lieux_anim": self.precisions_lieux_edit.text().strip() or None,
"accueil_pin": self.accueil_pin_check.isChecked(),
"theme_detaille": self.theme_detaille_edit.text().strip() or None,
"code_type_anim": self.theme_combo.current_data(),
"payant": self.payant_check.isChecked(),
"type_annul": type_annul,
"remarques": self.remarques_edit.text().strip() or None,
"type_dossier_ens": type_dossier,
"realise_par_tiers": realise_tiers,
"detail_tiers": self.detail_tiers_edit.text().strip() if realise_tiers else None,
}
def _reset_form(self):
self.date_edit.setDate(QDate.currentDate())
self.duree_h.setValue(0)
self.duree_min.setValue(0)
self.prepa_spin.setValue(0)
self.animateurs_widget.list_widget.clear()
self.type_groupe_combo.combo.setCurrentIndex(0)
self.precisions_groupe_edit.clear()
self.etab_combo.combo.setCurrentIndex(0)
self.commune_label.setText("")
self.enfants_spin.setValue(0)
self.adultes_spin.setValue(0)
self.lieux_combo.combo.setCurrentIndex(0)
self.precisions_lieux_edit.clear()
self.accueil_pin_check.setChecked(False)
self.theme_combo.combo.setCurrentIndex(0)
self.theme_detaille_edit.clear()
self.payant_check.setChecked(False)
self.annul_combo.combo.setCurrentIndex(0)
self.remarques_edit.clear()
self.dossier_combo.combo.setCurrentIndex(0)
self.tiers_check.setChecked(False)
self.detail_tiers_edit.clear()
def _save(self):
try:
data = self._collect_data()
if self._edit_mode:
self.db.update_donnees_animation(self._edit_code, data)
QMessageBox.information(self, "Succès", f"Animation #{self._edit_code} mise à jour.")
self._reload_animations_list()
else:
code = self.db.get_next_code_animation()
data['code_animation'] = code
self.db.insert_donnees_animation(data)
QMessageBox.information(self, "Succès", f"Animation #{code} enregistrée.")
self._reload_animations_list()
self.accept()
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))
def _save_and_new(self):
try:
data = self._collect_data()
code = self.db.get_next_code_animation()
data['code_animation'] = code
self.db.insert_donnees_animation(data)
QMessageBox.information(self, "Succès", f"Animation #{code} enregistrée.")
self._reload_animations_list()
self._new_form()
except Exception as e:
QMessageBox.critical(self, "Erreur", str(e))