diff --git a/sources/ui/configpage/generalconfigurationpage.cpp b/sources/ui/configpage/generalconfigurationpage.cpp
index 05688b006..6dd1916e8 100644
--- a/sources/ui/configpage/generalconfigurationpage.cpp
+++ b/sources/ui/configpage/generalconfigurationpage.cpp
@@ -395,9 +395,6 @@ void GeneralConfigurationPage::applyConf()
if (!ui->m_live_assistant->isChecked()) LiveServer::instance().stop();
#endif
}
- //What an assistant reads about this QElectroTech follows the change
- AssistantInfo::write();
-
//GENERIC PANEL
settings.setValue("genericpanel/folio",ui->m_use_folio_label->isChecked());
@@ -565,6 +562,12 @@ void GeneralConfigurationPage::applyConf()
diagram->update();
}
}
+
+ //What an assistant reads about this QElectroTech follows the
+ //change. Written last: the collection and title block paths are
+ //applied above, and an assistant launching a headless run takes
+ //the user and company collections from this file.
+ AssistantInfo::write();
}
/**
diff --git a/tests/qttest/CMakeLists.txt b/tests/qttest/CMakeLists.txt
index 6dab05931..e81ce96fc 100644
--- a/tests/qttest/CMakeLists.txt
+++ b/tests/qttest/CMakeLists.txt
@@ -267,6 +267,10 @@ endfunction()
# alone and with a group.
qet_add_app_test(tst_rotateselectionimage tst_rotateselectionimage.cpp)
+# Accepting the settings dialog writes qet-assistant.json with the
+# collection paths just chosen, not the ones they replace.
+qet_add_app_test(tst_assistantinfopaths tst_assistantinfopaths.cpp)
+
# Escape during a picture's resize, rotate or pivot drag puts it back, keeps
# it selected and records no undo step (#1414); the key goes to the view.
qet_add_app_test(tst_imagehandleescape tst_imagehandleescape.cpp)
diff --git a/tests/qttest/tst_assistantinfopaths.cpp b/tests/qttest/tst_assistantinfopaths.cpp
new file mode 100644
index 000000000..96e99dd67
--- /dev/null
+++ b/tests/qttest/tst_assistantinfopaths.cpp
@@ -0,0 +1,100 @@
+/*
+ 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 .
+*/
+#include "qetapptest.h"
+#include "scripting/assistantinfo.h"
+#include "ui/configpage/generalconfigurationpage.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ qet-assistant.json names the user and company collections, and the qet
+ MCP server hands them to every headless run it starts. Accepting the
+ settings dialog wrote the file before the dialog applied the new
+ collection paths, so the file kept the old ones: a company collection
+ chosen in the dialog stayed unknown to the assistant, and company://
+ paths failed in its runs, until QElectroTech was started again.
+*/
+class tst_assistantinfopaths : public QObject
+{
+ Q_OBJECT
+
+ static QString writtenPath(const QString &key)
+ {
+ QFile file(AssistantInfo::path());
+ if (!file.open(QIODevice::ReadOnly))
+ return QString();
+ const QJsonObject folders = QJsonDocument::fromJson(file.readAll())
+ .object().value(QStringLiteral("folders")).toObject();
+ return QDir::cleanPath(folders.value(key).toString());
+ }
+
+ static void choose(GeneralConfigurationPage &page, const QString &box, const QString &path)
+ {
+ auto *combo = page.findChild(box);
+ QVERIFY(combo);
+ //The state the page itself leaves once a folder is picked;
+ //signals blocked, or index 1 opens the folder dialog
+ const QSignalBlocker blocker(combo);
+ combo->setCurrentIndex(1);
+ combo->setItemData(1, path, Qt::DisplayRole);
+ }
+
+private slots:
+ void companyCollectionChosenInTheDialogIsWritten()
+ {
+ QTemporaryDir company;
+ QVERIFY(company.isValid());
+
+ GeneralConfigurationPage page;
+ choose(page, QStringLiteral("m_company_elmt_path_cb"), company.path());
+ page.applyConf();
+
+ QCOMPARE(writtenPath(QStringLiteral("elements_company")),
+ QDir::cleanPath(company.path()));
+ }
+
+ void customCollectionChosenInTheDialogIsWritten()
+ {
+ QTemporaryDir custom;
+ QVERIFY(custom.isValid());
+
+ GeneralConfigurationPage page;
+ choose(page, QStringLiteral("m_custom_elmt_path_cb"), custom.path());
+ page.applyConf();
+
+ QCOMPARE(writtenPath(QStringLiteral("elements_custom")),
+ QDir::cleanPath(custom.path()));
+ }
+};
+
+int main(int argc, char **argv)
+{
+ //AssistantInfo writes to the standard data folder, whatever
+ //--data-dir says, and QETApp writes it as its editor opens: test
+ //mode from the very start keeps the user's own file out of reach.
+ QStandardPaths::setTestModeEnabled(true);
+ return QetAppTest::run(argc, argv);
+}
+
+#include "tst_assistantinfopaths.moc"