51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Modèles de données partagés par l'application."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
|
|
|
|
@dataclass
|
|
class Clip:
|
|
"""Un extrait de texte capturé sur une page web."""
|
|
|
|
text: str
|
|
title: str
|
|
url: str
|
|
captured_at: datetime
|
|
# Si True, cet extrait s'enchaîne directement dans le suivant (même
|
|
# chapitre) : pas de nouveau titre/entrée de sommaire ni de saut de
|
|
# page à l'export — voir group_into_chapters() ci-dessous et
|
|
# main_window.py (bascule via l'icône entre deux extraits de la liste).
|
|
linked_to_next: bool = False
|
|
|
|
def preview(self, length: int = 60) -> str:
|
|
"""Retourne un aperçu court du texte, sur une seule ligne."""
|
|
flat = " ".join(self.text.split())
|
|
if len(flat) <= length:
|
|
return flat
|
|
return flat[: length - 1].rstrip() + "…"
|
|
|
|
|
|
def group_into_chapters(clips: list[Clip]) -> list[list[int]]:
|
|
"""Regroupe les indices de `clips` en chapitres : une suite d'extraits
|
|
consécutifs reliés par `linked_to_next` forme un seul chapitre (un
|
|
seul titre/une seule entrée de sommaire à l'export). Un extrait non
|
|
lié forme un chapitre à lui seul.
|
|
|
|
Utilisé à la fois par pdf_builder.py (export) et par l'UI
|
|
(main_window.py, preview_window.py) pour une définition unique et
|
|
cohérente des regroupements.
|
|
"""
|
|
chapters: list[list[int]] = []
|
|
current: list[int] = []
|
|
for index, clip in enumerate(clips):
|
|
current.append(index)
|
|
if not clip.linked_to_next:
|
|
chapters.append(current)
|
|
current = []
|
|
if current: # défensif : n'arrive que si le dernier extrait est lié à "rien"
|
|
chapters.append(current)
|
|
return chapters
|