mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-01 23:54:13 +02:00
Settings: configure the folder prefixes of the user collection
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.
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "../qetgraphicsitem/element.h"
|
||||
#include "../qetxml.h"
|
||||
#include "../qetproject.h"
|
||||
#include "../ElementsCollection/qetlabelsfile.h"
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QStringList>
|
||||
@@ -705,74 +706,6 @@ namespace autonum
|
||||
return formula;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief prefixFromLabelFile
|
||||
Look up a prefix for @a path (path[dirLevel] outermost, path[1] the
|
||||
deepest directory; path[0], the element's own file name, is never
|
||||
matched) in the qet_labels.xml at @a filepath.
|
||||
|
||||
Descends through nested \<category name="..."\> elements matching
|
||||
path[dirLevel], path[dirLevel-1], ..., path[1] in turn, considering
|
||||
only *direct* children at each step -- unlike a flat token scan,
|
||||
this cannot be fooled by a same-named category living elsewhere in
|
||||
the document at the wrong nesting depth (bugtracker #671 item 5).
|
||||
|
||||
At each matched level, that category's own \<prefix\> child -- even
|
||||
an empty one -- overrides whatever a shallower ancestor already
|
||||
provided, so an explicit empty \<prefix/\> cancels inheritance
|
||||
rather than silently falling back to it (the behaviour requested in
|
||||
PR #686 review). A category with no \<prefix\> child at all leaves
|
||||
the inherited value untouched, which is how a directory with no
|
||||
prefix of its own comes to inherit its parent's, as the file's own
|
||||
header comment documents.
|
||||
|
||||
@return the prefix that applies, or a null QString if the file
|
||||
cannot be read, is not well-formed, or does not describe this
|
||||
path at all (as opposed to describing it with no prefix
|
||||
anywhere along it, which is a non-null empty string).
|
||||
*/
|
||||
static QString prefixFromLabelFile(const QString &filepath, const QStringList &path, int dirLevel)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return QString();
|
||||
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&file))
|
||||
return QString();
|
||||
|
||||
QDomElement node = document.documentElement();
|
||||
if (node.isNull())
|
||||
return QString();
|
||||
|
||||
QString prefix;
|
||||
for (int i = dirLevel ; i >= 1 ; --i) {
|
||||
QDomElement child = node.firstChildElement(QStringLiteral("category"));
|
||||
while (!child.isNull()
|
||||
&& child.attribute(QStringLiteral("name")) != path[i]) {
|
||||
child = child.nextSiblingElement(QStringLiteral("category"));
|
||||
}
|
||||
if (child.isNull())
|
||||
return QString();
|
||||
node = child;
|
||||
|
||||
const QDomElement own = node.firstChildElement(QStringLiteral("prefix"));
|
||||
if (!own.isNull()) {
|
||||
//readElementText()'s null-vs-empty distinction that PR
|
||||
//#686 needed for the old QXmlStreamReader-based lookup
|
||||
//has a QDomElement equivalent: text() on an empty
|
||||
//element can itself come back null depending on how the
|
||||
//XML was written, so the same explicit fallback applies
|
||||
//-- an empty QString here means "found, deliberately
|
||||
//blank", not "not found".
|
||||
prefix = own.text();
|
||||
if (prefix.isNull())
|
||||
prefix = QString("");
|
||||
}
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief elementPrefixForLocation
|
||||
@param location
|
||||
@@ -831,7 +764,7 @@ namespace autonum
|
||||
{
|
||||
const QString common_file = QDir(QETApp::commonElementsDir())
|
||||
.filePath(collection_root + QStringLiteral("/qet_labels.xml"));
|
||||
const QString prefix = prefixFromLabelFile(common_file, path, dirLevel);
|
||||
const QString prefix = QetLabelsFile::prefixForPath(common_file, path, dirLevel);
|
||||
if (!prefix.isNull()) {
|
||||
return prefix;
|
||||
}
|
||||
@@ -859,7 +792,7 @@ namespace autonum
|
||||
const QString candidate =
|
||||
QDir(dir).filePath(QStringLiteral("qet_labels.xml"));
|
||||
for (const QStringList &segments : {path_from_root, path}) {
|
||||
const QString prefix = prefixFromLabelFile(
|
||||
const QString prefix = QetLabelsFile::prefixForPath(
|
||||
candidate, segments, segments.size() - 1);
|
||||
if (!prefix.isNull()) {
|
||||
return prefix;
|
||||
|
||||
Reference in New Issue
Block a user