mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-02 16:44:16 +02:00
6ea626fec7
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.
105 lines
4.0 KiB
C++
105 lines
4.0 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef QETLABELSFILE_H
|
|
#define QETLABELSFILE_H
|
|
|
|
#include <QCoreApplication>
|
|
#include <QDomDocument>
|
|
#include <QList>
|
|
#include <QSet>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
|
|
class QIODevice;
|
|
|
|
/**
|
|
@brief The QetLabelsFile class
|
|
|
|
Represents the qet_labels.xml file of an elements collection : the file
|
|
that maps every directory of the collection to the prefix (the ISO/IEC
|
|
81346 label) given to the elements it contains.
|
|
|
|
Two kind of users use this class :
|
|
- the prefix lookup performed when an element is placed in a project
|
|
(prefixForPath(), see also autonum::elementPrefixForLocation())
|
|
- the "Configurer les préfixes…" editor, which loads a file (creating a
|
|
skeleton in memory when there is none yet), shows the folder tree of
|
|
the collection next to the stored prefixes, and writes everything back
|
|
in one go when the user validates.
|
|
|
|
Nothing is written to the disk before save() is called, so cancelling the
|
|
editor really leaves the collection untouched.
|
|
*/
|
|
class QetLabelsFile
|
|
{
|
|
Q_DECLARE_TR_FUNCTIONS(QetLabelsFile)
|
|
|
|
public:
|
|
QetLabelsFile() = default;
|
|
|
|
// methods
|
|
public:
|
|
static QString labelsFilePath(const QString &collection_dir);
|
|
static QList<QStringList> scanFolders(const QString &collection_dir);
|
|
static QString prefixForPath(const QString &filepath, const QStringList &path, int dirLevel);
|
|
static QString prefixInDocument(const QDomDocument &document, const QStringList &path, int dirLevel);
|
|
|
|
bool load(const QString &collection_dir);
|
|
QString prefix(const QStringList &relative_path) const;
|
|
QStringList orphanPaths(const QList<QStringList> &folders) const;
|
|
void ensureStructure(const QList<QStringList> &folders);
|
|
void setPrefix(const QStringList &relative_path, const QString &prefix);
|
|
int removeOrphans(const QList<QStringList> &folders);
|
|
bool save();
|
|
|
|
QString filePath() const {return m_file_path;}
|
|
QString backupPath() const {return m_backup_path;}
|
|
QString errorString() const {return m_error;}
|
|
///true when the existing file was found unusable and had to
|
|
///be backed up before an empty document was used instead
|
|
bool isBroken() const {return m_broken;}
|
|
///what exactly is wrong with that file (line and column of
|
|
///the syntax error for instance), so the caller can tell the
|
|
///user how to repair it instead of silently rebuilding it
|
|
QString brokenReason() const {return m_broken_reason;}
|
|
|
|
private:
|
|
static bool parse(QIODevice &device, QDomDocument &document, QString *reason);
|
|
QDomElement categoryForPath(const QStringList &relative_path, bool create);
|
|
void createEmptyDocument();
|
|
QString backupBrokenFile();
|
|
static void scanRec(const QString &path, const QStringList &relative_path, QList<QStringList> &out);
|
|
static QDomElement directChildCategory(const QDomElement &parent, const QString &name);
|
|
static void collectOrphans(const QDomElement &parent, const QString &relative_path, const QSet<QString> &folders_key, QList<QDomElement> &orphans);
|
|
static QString serialize(const QDomDocument &document);
|
|
|
|
// attributes
|
|
private:
|
|
QString m_file_path;
|
|
QString m_backup_path;
|
|
QString m_error;
|
|
QString m_broken_reason;
|
|
QString m_snapshot;
|
|
bool m_file_exists = false;
|
|
bool m_force_save = false;
|
|
bool m_broken = false;
|
|
QDomDocument m_document;
|
|
};
|
|
|
|
#endif // QETLABELSFILE_H
|