ODT footnote import

Previous topic - Next topic

chalavi

Hi, I'm an old user of Scribus (thank's for the team) and always has problems with footnotes.
With Claude, we have made some modifications to the code (odt2im) and a footnote system is running. Not perfect of course but usuable even for big document.
Ask for the modified files (importodt.cpp and importodt.h) if you want to compile Scribus with this adapted version (ask for version Scribus 1.6.6 or Scribus 1.7.3)
Here is the story in english and in french.

Vic

----------------------------------------------------------------------------
# [EN] ODT footnote import: why we dropped Scribus's native notes system

I'm developing, with valuable help from Claude (Anthropic), an addition to the ODT import plugin (`odt2im`) to handle footnotes — until now completely ignored on import (`text:note` simply wasn't recognized). Use case: historical booklets made of about ten articles per issue, each imported from a `.odt` file written in LibreOffice by a different author, with footnotes used regularly.

## First approach: going through Scribus's notes system

The first version converted each ODT note into a real Scribus `Mark`/`TextNote` object, attached to a `NotesStyle` configured as an endnote (simpler to auto-materialize than a classic footnote). It worked... up to a point.

On realistic documents (several hundred pages, 1000+ notes), we ran into several distinct instabilities in a row, all located in Scribus's native notes-handling code (not in our plugin):

- `PageItem_NoteFrame::layout()` crashes (SIGSEGV) on an unguarded dereference of `m_masterFrame`, when automatic width adjustment is enabled on an endnotes-type style with no master frame.
- Same issue in `ScribusDoc::updateNotesFramesSettings()`, this time with automatic welding (`AutoWeld`).
- Switching from endnotes to footnotes from the Notes Styles editor enters an infinite loop on a large document (`PageItem_NoteFrame::layout()` and `ScribusDoc::updateMarks()` repeatedly calling into each other without ever converging) — confirmed by two `gdb` snapshots taken a few minutes apart, with strictly identical call stacks.
- Superscripts (ordinal suffixes like "XIVe siècle") inside note bodies end up visibly, excessively shrunk: the source ODT already encodes a reduced font size for those characters, and Scribus applies its own automatic superscript scaling on top of that — a compounding effect that doesn't happen the same way in the main body text.

Each of these was individually worked around on the plugin side (disabling options on the `NotesStyle`, etc.), but taken together they raised a real question: is this system, as it currently stands, reliable at this scale?

## Second, simpler approach: plain-text notes

We ended up dropping the `Mark`/`TextNote`/`NotesStyle` system entirely. Now:

- The note reference in the main text is just a superscript number, written as ordinary text (the same formatting mechanism as any other superscript in the document — so no more compounded size reduction).
- Each note's content is collected while parsing, then appended at the end of the article as a numbered list, by directly reusing the plugin's existing functions for the main body text (`parseTextParagraph`/`parseTextSpan`) — so the same formatting fidelity (fonts, character styles, superscripts...), with no separate conversion code to maintain.
- Note text is appended right after the main text, in the same frame — the plugin never creates a page or frame itself. Any overflow is left to Scribus's native features (automatic text frames / unlinking frames with automatic text flow) rather than reimplementing pagination logic ourselves.

## The trade-off, stated plainly

This approach loses two things the native system provided:
- **Automatic renumbering**: numbers are frozen at import time. Reordering notes afterward in Scribus means renumbering by hand.
- The **footnote/endnote toggle** built into the Notes Styles editor — which no longer applies here, obviously.

For our workflow (import once per article, then layout/proofreading, with no later re-editing of the notes themselves), that's a clearly acceptable trade-off given the robustness gained.

## Why post this

Two reasons for sharing this here rather than keeping it to ourselves:
1. If anyone else is developing or maintaining an import/export feature touching Scribus's notes system, these instabilities (already reported separately on the tracker, with GDB traces) might be worth knowing about before relying on it at scale.
2. If anyone has already run into — and possibly worked around differently — these same limitations of the native notes system, I'd welcome any feedback before taking this plugin further.

---

# [FR] Import des notes de bas de page ODT : pourquoi on a abandonné le système de notes natif de Scribus

Je développe, avec l'aide précieuse de Claude (Anthropic), un ajout au plugin d'import ODT (`odt2im`) pour gérer les notes de bas de page — jusqu'ici totalement ignorées à l'import (`text:note` n'était simplement pas reconnu). Le cas d'usage : des cahiers historiques composés d'une dizaine d'articles par numéro, chacun importé depuis un fichier `.odt` rédigé sous LibreOffice par un auteur différent, avec un usage courant des notes de bas de page.

## Première approche : passer par le système de notes de Scribus

La première version convertissait chaque note ODT en un vrai objet `Mark`/`TextNote` Scribus, rattaché à un `NotesStyle` configuré en note de fin (endnote — plus simple à matérialiser automatiquement qu'une note de bas de page classique). Ça fonctionnait... jusqu'à un certain point.

Sur des documents réalistes (plusieurs centaines de pages, 1000+ notes), on a enchaîné plusieurs instabilités bien distinctes, toutes situées dans le code natif de gestion des notes de Scribus (pas dans notre plugin) :

- `PageItem_NoteFrame::layout()` plante (SIGSEGV) sur un déréférencement de `m_masterFrame` non protégé, quand l'ajustement automatique de largeur est actif sur un style de notes de fin sans cadre maître.
- Même chose côté `ScribusDoc::updateNotesFramesSettings()`, avec le soudage automatique (`AutoWeld`) cette fois.
- La bascule notes de fin → notes de bas de page, depuis l'éditeur de styles de notes, entre dans une boucle infinie sur un document volumineux (`PageItem_NoteFrame::layout()` ↔ `ScribusDoc::updateMarks()` qui se rappellent mutuellement sans jamais converger) — confirmé par deux instantanés `gdb` strictement identiques à quelques minutes d'écart.
- Les exposants (ordinaux type « XIVe siècle ») dans le corps des notes ressortent visuellement rétrécis à l'excès : l'ODT source encode déjà une taille de police réduite pour ces caractères, et Scribus applique par-dessus sa propre mise à l'échelle automatique de l'exposant — un cumul qui ne se produit pas de la même façon dans le texte principal.

Chacun de ces points a été contourné individuellement côté plugin (désactivation d'options sur le `NotesStyle`, etc.), mais leur accumulation a fini par poser une vraie question de fond : est-ce que ce système, dans son état actuel, est fiable à cette échelle ?

## Deuxième approche, plus simple : des notes en texte plein

On a fini par abandonner entièrement le système `Mark`/`TextNote`/`NotesStyle`. Désormais :

- L'appel de note dans le texte principal est un simple chiffre en exposant, écrit comme du texte normal (même mécanisme de mise en forme que n'importe quel autre exposant du document — donc plus de double réduction de taille).
- Le contenu de chaque note est accumulé pendant le parsing, puis ajouté en fin d'article sous forme de liste numérotée, en réutilisant **directement** les fonctions existantes du plugin qui gèrent déjà le texte principal (`parseTextParagraph`/`parseTextSpan`) — donc la même richesse de mise en forme (polices, styles de caractères, exposants...), sans code de conversion séparé à maintenir.
- Le texte des notes est ajouté à la suite du texte principal, dans le même cadre — pas de création de page ou de cadre par le plugin. En cas de débordement, on s'appuie sur les fonctionnalités natives de Scribus (cadres de texte automatiques / délier avec découpe automatique du texte) plutôt que de réimplémenter une gestion de pagination.

## Le compromis assumé

Cette approche perd deux choses que le système natif offrait :
- La **renumérotation automatique** : les numéros sont figés au moment de l'import. Si on modifie l'ordre des notes après coup dans Scribus, il faut renuméroter à la main.
- La **bascule footnote/endnote** intégrée à l'éditeur de styles de notes — qui n'a plus de sens ici, forcément.

Pour notre flux de travail (import une fois par article, puis mise en page/relecture, sans réédition ultérieure des notes elles-mêmes), c'est un compromis largement acceptable au regard du gain en robustesse.

## Pourquoi ce message

Deux raisons de le partager ici plutôt que de garder ça pour nous :
1. Si quelqu'un d'autre développe ou maintient un import/export touchant aux notes de Scribus, ces instabilités (déjà remontées sur le tracker séparément, avec traces GDB) sont peut-être utiles à connaître avant de s'appuyer dessus à grande échelle.
2. Si quelqu'un a déjà rencontré — et éventuellement contourné autrement — ces mêmes limites du système de notes natif, je suis preneur de retours avant d'aller plus loin sur ce plugin.

buttar

That seems cool. Did you post the code somewhere? Share it with the devs so they can review it?

a.l.e

I guess that for many workflows, having "static" footnotes is more than good enough!

But if somebody has a friend named Claude that can help fixing the references in Scribus, they're welcome : - )

chalavi

Here is the zip file (scribus_sources-1.7.3/scribus/plugins/gettext/)
These files are for Scribus 1.7.3.
Note : All the styles from Libreoffice are imported (used or unused). More than 400 styles... but there is an option in Scribus 1.7.3 (not in 1.6.6) which permit to delete all unused styles.

chalavi

This i a second release of my ODT import and it follows my workflow and historical needs.
For memory, my association is dedicated to edit historical books with a lot of authors and also students. We have made more than 25 books in the last 4 years. A classic case is to receive a 200/300 A4 format pages with poor image treatment but the willing to present the best from the author point of vue. After a few discussions and explanations, the author may make minor edits to their text and images. Even so, graphic guidelines are almost never followed.
So,how does a graphic designer's workflow look like?
They receive a .docx or an .odf file. If it is a .docx, they quickly convert it to .odt before importing it.
They start by deleting all unused styles and removing empty paragraphs (a typographic rule), then take inventory (which is automatic in this version of the ODT import).
Next, they adjust their styles while taking care not to overwrite local text formatting (superscripts, italics, small caps, etc.). They do the same for footnotes.
Then, they logically split the imported text block—which spans from the first to the last page—according to the book's chapters. Adjustments and text reflows will then only affect a single chapter, which is more than enough.
They do the same for the footnote text frames.
Once the styles and text are cleaned up, and the main text and footnotes are split into sections, they begin adjusting the main text (removing widows and orphans, adjusting tracking/letter-spacing, etc.) alongside the footnote area and any images to be placed on the page.
When it comes to images, the designer mostly needs visual markers. In this version of the ODT import, images are brought in as thumbnails ready to be positioned. The import tool cannot know where to actually place these images, as that depends on how they were anchored in the ODT file—especially since most source files use A4 format, whereas books rarely match those dimensions.
The goal of this import process is not to attempt an exact replica of the original file, which is impossible, but to assist the designer by eliminating the heavy burden of re-typesetting everything or recreating footnotes from scratch. Everything is laid out and ready for composition and final adjustments.

# [EN] ODT import plugin — summary of this version

This version of the ODT import plugin (`odt2im`) adds the following, on top of the base Scribus import:

- **Footnotes** (`text:note`): the call-out number is inserted as superscript text in the main flow; each note's content is appended as a numbered list at the end of the article, reusing the plugin's own paragraph/span parsing (same fonts, styles, formatting). Numbering restarts at 1 per article.
- **Images** (`draw:frame`/`draw:image`, including captioned ones): extracted to an `images/` subfolder next to the source `.odt`. Each image is placed as an independent frame at a fixed 30 mm width (height scaled to preserve the original proportions, no distortion), with text flow disabled — the surrounding text does not wrap around it. Frames are placed on the page roughly corresponding to their position in the source text (or their source page number, for images anchored "to the page"), stacked one under another when several land on the same page. This is a placement aid for layout, not a finished result — manual repositioning is expected either way.
- **Empty paragraphs**: paragraphs with no actual content (a common LibreOffice habit for manual spacing) are no longer imported as blank lines — paragraph spacing is left to Scribus's own paragraph styles.
- **Unused named styles**: only the named paragraph/character styles actually applied to some imported text are created in the Scribus document — not every style defined by the source LibreOffice template, most of which a given article never uses.

Tested end to end on real, large documents (footnotes, images, and styles together on a 300+ page book).

With valuable help from Claude (Anthropic).

---

# [FR] Plugin d'import ODT — synthèse de cette version

Cette version du plugin d'import ODT (`odt2im`) ajoute ce qui suit, en plus de l'import de base de Scribus :

- **Notes de bas de page** (`text:note`) : l'appel de note est inséré en exposant dans le texte principal ; le contenu de chaque note est ajouté sous forme de liste numérotée en fin d'article, en réutilisant directement les fonctions de parsing du plugin (mêmes polices, styles, mise en forme). La numérotation repart à 1 à chaque article.
- **Images** (`draw:frame`/`draw:image`, y compris avec légende) : extraites vers un sous-dossier `images/` à côté du `.odt` source. Chaque image est placée dans un cadre indépendant à une largeur fixe de 30 mm (hauteur recalculée pour conserver ses proportions d'origine, sans déformation), avec l'habillage désactivé — le texte ne la contourne plus. Les cadres sont placés sur la page correspondant approximativement à leur position dans le texte source (ou à leur numéro de page source, pour les images ancrées « à la page »), empilés les uns sous les autres quand plusieurs tombent sur la même page. C'est un repère de montage, pas un résultat fini — un repositionnement manuel reste de toute façon nécessaire.
- **Paragraphes vides** : les paragraphes sans contenu réel (habitude courante de LibreOffice pour espacer manuellement) ne sont plus importés comme des lignes vides — l'espacement entre paragraphes reste du ressort des styles Scribus.
- **Styles nommés inutilisés** : seuls les styles de paragraphe/caractère réellement appliqués à du texte importé sont créés dans le document Scribus — pas l'ensemble des styles définis par le modèle LibreOffice source, dont un article donné n'utilise généralement qu'une fraction.

Testé de bout en bout sur des documents réels et volumineux (notes, images et styles ensemble sur un livre de plus de 300 pages).

Avec l'aide précieuse de Claude (Anthropic).