Review findings on the prefix editor:
- OK without touching anything changed the file: every row was written
back, so an explicit <prefix/>, which reads as an empty field and
cancels the inheritance, was dropped and that folder started
inheriting its parent's prefix again. A row is now written only when
it was edited or no longer holds what the file has, and the two kinds
of empty field look different: hasPrefix() tells an explicit
<prefix/> from a missing one, which is what the field hint shows.
- load() copied a broken file aside before the user had chosen
anything, so every "Corriger le fichier" left a .bak behind while the
message said nothing had been modified. The copy is now made by
save(), right before the file is replaced: repairing or cancelling
leaves nothing behind, and a copy that cannot be made stops the write
rather than destroying the only copy.
- The button followed the combo box only for "Parcourir...": put back
on "Par defaut" it fell back to the previously saved path instead of
the default one. The directory of the entry being displayed is now
used, "Par defaut" being dataDir()/elements/.
The prefixes of a collection's folders live in a qet_labels.xml that so
far could only be edited by hand, and a hand-edited file is easy to
break: one extra </category> and the file stops being well formed, which
the lookup answers with "no prefix at all". Labels then degrade
silently, without any error anywhere - the file is simply ignored. Add
a way to edit it from the settings.
- "Configurer les préfixes…" next to the user collection path opens
PrefixConfigurationDialog, which lists every folder of that
collection, subfolders included, one line edit each, with "Tout
déplier"/"Tout replier" and OK/Abbrechen. It writes on OK only :
cancelling leaves the collection exactly as it was, and an emptied
field drops the <prefix> again so the folder goes back to inheriting
its parent's.
- QetLabelsFile owns the reading, scanning, structure building and
writing of the file. prefixFromLabelFile() moves there unchanged from
assignvariables.cpp as prefixForPath(), so the lookup used by label
assignment and the one used by the dialog are one piece of code.
- Entries whose folder no longer exists on disk are offered as
Conserver or Supprimer and only applied on OK.
- An unparsable file is copied to qet_labels.xml.bak first, and the
dialog then reports the line and column of the syntax error, with
"Corriger le fichier" as the default choice - such a file may be one
forgotten tag away from being valid - and rebuilds the whole
structure only when "Reconstruire" is picked. A broken file that
cannot be backed up is refused rather than overwritten.
The scan reads non-hidden directories recursively in name order,
without following symlinks. A collection without any subfolder has
nothing to configure and says so instead of opening an empty dialog.
Tests: a standalone harness kept outside the tree (84 checks :
structure, inheritance, explicit empty prefix, orphan handling, broken
file, wrong root element, broken file whose backup cannot be written,
reload after save) and the dialog driven offscreen (29 checks,
including "reject creates no file"). ctest 27/28, the failing
tst_menubarkeyboard being the headless F10 test, unrelated to this.
The new strings are French source strings like the rest of the code;
the .ts files are left to the translation update.