From 87a010eb757e29fe16a6dd95da9b58a1e1e42519 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 2 Aug 2026 01:36:11 +1200 Subject: [PATCH] Never leave a collection folder without a name, and say when it is broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://qelectrotech.org/bugtracker/view.php?id=332 localName() set a non-root folder's label only inside the success path of loading its qet_directory file. If that load failed -- file missing, malformed, or unopenable because of the Windows path-encoding problem with accented characters that plc-user diagnosed on the tracker -- nothing was set at all, and since a fresh item's text() is null the folder rendered with a completely blank label. That is the reported symptom. Resolve the name into a local and always fall back to the folder's own directory name, so the label is never empty whatever went wrong. The fallback is applied *after* NamesList::name() rather than passed into it. This matters: name() returns a caller-supplied fallback before it reaches its "first available translation" step, so passing m_path in would replace a perfectly good name in some other language with the raw directory name. A folder named only in French, viewed under an English locale, previously showed "Accentué" and must keep doing so. Falling back on its own would then hide the broken file -- the user sees a plausible name and never learns there is anything to repair. So a folder whose qet_directory could not be read now says so in its tooltip, naming the file, above the collection path that tooltip already carried. Suggested by plc-user on PR #622. The flag is recorded in localName() and consumed in setUpData(), because setUpData() assigns the tooltip after localName() runs and would otherwise discard it. Only a file-level failure is flagged. A readable qet-directory with no entry for the current language is not an error; NamesList::name() resolves that itself and no warning is shown. Verified on a fixture collection of four folders -- valid, malformed, missing, and one named only in French: master this patch fr-only Accentué Accentué (no warning) malformed malformed (warning) no qet_directory no_file (warning) valid Valid Folder Valid Folder (no warning) --- .../fileelementcollectionitem.cpp | 43 +++++++++++++++++-- .../fileelementcollectionitem.h | 5 +++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/sources/ElementsCollection/fileelementcollectionitem.cpp b/sources/ElementsCollection/fileelementcollectionitem.cpp index b14e86088..013ee0153 100644 --- a/sources/ElementsCollection/fileelementcollectionitem.cpp +++ b/sources/ElementsCollection/fileelementcollectionitem.cpp @@ -136,18 +136,41 @@ QString FileElementCollectionItem::localName() } else { + // Fall back to the raw directory name (m_path) whenever the + // translated name can't be obtained -- qet_directory missing, + // unreadable (e.g. a Windows path-encoding issue with special + // characters, see bugtracker #332), malformed, or present but + // without a usable name entry -- rather than leaving the item + // blank. + QString display_name; + bool readable = false; QString str(fileSystemPath() % "/qet_directory"); pugi::xml_document docu; - if(docu.load_file(str.toStdWString().c_str())) + if (docu.load_file(str.toStdWString().c_str())) { if (QString(docu.document_element().name()) == "qet-directory") { + readable = true; NamesList nl; nl.fromXml(docu.document_element()); - setText(nl.name()); + // Deliberately no fallback argument: a non-empty one + // is returned *before* NamesList::name() reaches its + // "first available translation" step, so passing + // m_path here would replace a perfectly good name in + // some other language with the raw directory name. + // The fallback belongs after the chain, not inside it. + display_name = nl.name(); } } + setText(display_name.isEmpty() ? m_path : display_name); + + // Only a file-level failure counts: a readable qet-directory + // with no entry for the current language is not an error, + // NamesList::name() resolves that on its own. Recorded here + // and reported by setUpData(), which sets the tooltip after + // this runs. + m_qet_directory_unreadable = !readable; } } else if (isElement()) { @@ -350,7 +373,21 @@ void FileElementCollectionItem::setUpData() } } - setToolTip(collectionPath()); + // Falling back to the raw directory name keeps the folder usable, but + // on its own it hides the fact that a file is broken: the user sees a + // plausible name and never learns there is anything to repair. Say so + // above the collection path, which stays as the last line the way the + // element tooltip above builds it. + QStringList tip; + if (isDir() && m_qet_directory_unreadable) + { + tip << QObject::tr("Le fichier « %1 » est absent ou illisible : " + "le nom traduit de ce dossier n'a pas pu être lu, " + "son nom de dossier est affiché à la place.") + .arg(fileSystemPath() % "/qet_directory"); + } + tip << collectionPath(); + setToolTip(tip.join(QLatin1Char('\n'))); } /** diff --git a/sources/ElementsCollection/fileelementcollectionitem.h b/sources/ElementsCollection/fileelementcollectionitem.h index d2c735d72..4c9885f79 100644 --- a/sources/ElementsCollection/fileelementcollectionitem.h +++ b/sources/ElementsCollection/fileelementcollectionitem.h @@ -64,6 +64,11 @@ class FileElementCollectionItem : public ElementCollectionItem private: QString m_path; + /// True when this directory's qet_directory file is missing or + /// unreadable, so setUpData() can say so in the tooltip. Recorded + /// rather than acted on in localName(), because setUpData() resets + /// the tooltip afterwards and would otherwise discard it. + bool m_qet_directory_unreadable = false; }; #endif // FILEELEMENTCOLLECTIONITEM2_H