Settings: only write the prefix rows that were edited

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/.
This commit is contained in:
Kellermorph
2026-09-30 11:01:31 +02:00
parent 03bffa96c7
commit 1d339a8b27
4 changed files with 104 additions and 36 deletions
@@ -650,13 +650,20 @@ void GeneralConfigurationPage::on_m_user_macros_path_cb_currentIndexChanged(int
*/
void GeneralConfigurationPage::on_m_prefix_pb_clicked()
{
//The directory currently shown in the combo is the one this page
//displays, even when it has not been applied yet, while
//QETApp::customElementsDir() still returns the previously saved
//path : follow what the user sees.
//The directory the page displays, even when the change has not
//been applied yet : QETApp::customElementsDir() still answers with
//the previously saved path, which is not what is shown when the
//combo has been put back on "Par defaut".
QString directory;
if (ui->m_custom_elmt_path_cb->currentIndex() == 1) {
switch (ui->m_custom_elmt_path_cb->currentIndex()) {
case 1: //"Parcourir..." : the item itself holds the chosen path
directory = ui->m_custom_elmt_path_cb->itemData(1, Qt::DisplayRole).toString();
break;
case 0: //"Par defaut" : where a default custom collection lives
directory = QETApp::dataDir() + QStringLiteral("/elements/");
break;
default:
break;
}
if (directory.isEmpty()) {
directory = QETApp::customElementsDir();
@@ -704,9 +711,9 @@ void GeneralConfigurationPage::on_m_prefix_pb_clicked()
"Ouvrez le fichier dans un éditeur de texte à l'endroit indiqué, "
"corrigez-le puis relancez cette commande.\n\n"
"« Reconstruire » : l'arborescence des dossiers est recréée, "
"mais tous les préfixes actuels sont perdus."));
box.setDetailedText(tr("Fichier : %1\nCopie conservée : %2")
.arg(labels.filePath(), labels.backupPath()));
"mais tous les préfixes actuels sont perdus. Le fichier actuel "
"est conservé sous le nom qet_labels.xml.bak avant d'être remplacé."));
box.setDetailedText(tr("Fichier : %1").arg(labels.filePath()));
box.exec();
if (box.clickedButton() != rebuild_button) {
return;
+37 -3
View File
@@ -155,10 +155,27 @@ void PrefixConfigurationDialog::buildTree()
continue;
}
parent_item->setData(0, Qt::UserRole, folder);
//What the file holds for that folder, kept to tell a row the
//user touched from one they left alone (@see accept())
parent_item->setData(1, Qt::UserRole, m_labels.prefix(folder).trimmed());
auto *edit = new QLineEdit(m_labels.prefix(folder), m_tree);
auto *edit = new QLineEdit(m_labels.prefix(folder).trimmed(), m_tree);
edit->setClearButtonEnabled(true);
edit->setPlaceholderText(tr("hériter du dossier parent", "placeholder of an empty prefix field"));
//A folder whose file holds an explicit <prefix/> shows an empty
//field too, but does not inherit : say so instead of promising
//an inheritance that will not happen
edit->setPlaceholderText(m_labels.hasPrefix(folder)
? tr("aucun préfixe : n'hérite pas du parent",
"placeholder of an empty prefix field whose folder explicitly has no prefix, which cancels the inheritance")
: tr("hériter du dossier parent", "placeholder of an empty prefix field"));
connect(edit, &QLineEdit::textEdited, this, [parent_item, edit]() {
//Once the user has typed in the field, whatever it holds
//when OK is pressed is what the folder gets - an emptied
//field then means "inherit" again, even when the file had
//an explicit <prefix/>
parent_item->setData(1, Qt::UserRole + 1, true);
edit->setPlaceholderText(tr("hériter du dossier parent", "placeholder of an empty prefix field"));
});
edit->installEventFilter(this);
m_tree->setItemWidget(parent_item, 1, edit);
}
@@ -184,7 +201,17 @@ void PrefixConfigurationDialog::accept()
if (edit == nullptr) {
continue;
}
m_labels.setPrefix(item->data(0, Qt::UserRole).toStringList(), edit->text().trimmed());
const QString text = edit->text().trimmed();
//A row the user did not touch is left exactly as the file has
//it. Writing every field back would turn an explicit
//<prefix/>, which shows empty and cancels the inheritance,
//into no <prefix> at all, and that folder would silently start
//inheriting its parent's prefix again.
if (!item->data(1, Qt::UserRole + 1).toBool()
&& text == item->data(1, Qt::UserRole).toString()) {
continue;
}
m_labels.setPrefix(item->data(0, Qt::UserRole).toStringList(), text);
}
if (m_remove_orphans) {
@@ -199,6 +226,13 @@ void PrefixConfigurationDialog::accept()
return;
}
if (!m_labels.backupPath().isEmpty()) {
QMessageBox::information(this,
tr("Fichier endommagé remplacé"),
tr("Le fichier %1 était illisible : il a été remplacé.\nSa copie a été conservée sous :\n%2")
.arg(m_labels.filePath(), m_labels.backupPath()));
}
QDialog::accept();
}