Merge pull request #1410 from ispyisail/feature/settings-profile-parts

Add saving and loading only part of the settings
This commit is contained in:
ispyisail
2026-10-09 22:35:37 +13:00
committed by GitHub
4 changed files with 427 additions and 28 deletions
+5 -2
View File
@@ -187,10 +187,13 @@ target_link_libraries(tst_symbolscale PRIVATE Qt::Test)
# configprofile.h is header-only: which settings a saved configuration
# profile carries, and how loading one replaces the live settings.
add_executable(tst_configprofile tst_configprofile.cpp)
# borderproperties.cpp: the real writer of the folio size defaults, to check
# that what it writes falls in the part for new projects.
add_executable(tst_configprofile tst_configprofile.cpp
${QET_DIR}/sources/borderproperties.cpp)
add_test(NAME tst_configprofile COMMAND tst_configprofile)
target_include_directories(tst_configprofile PRIVATE ${QET_DIR}/sources)
target_link_libraries(tst_configprofile PRIVATE Qt::Test Qt::Gui)
target_link_libraries(tst_configprofile PRIVATE Qt::Test Qt::Gui Qt::Xml)
# itemgroups.cpp keeps group membership and the selection rule apart from
# Diagram, so it is tested here on a plain scene of rectangles.
+132
View File
@@ -2,6 +2,7 @@
#include <QTemporaryDir>
#include "utils/configprofile.h"
#include "borderproperties.h"
class tst_configprofile : public QObject
{
@@ -17,6 +18,7 @@ private slots:
QVERIFY(ConfigProfile::isLocalKey("diagrameditor/geometry"));
QVERIFY(ConfigProfile::isLocalKey("elementeditor/state"));
QVERIFY(ConfigProfile::isLocalKey("projects-recentfiles/file1"));
QVERIFY(ConfigProfile::isLocalKey("dialoggeometry/ConfigDialog"));
QVERIFY(ConfigProfile::isLocalKey(ConfigProfile::marker_key));
QVERIFY(!ConfigProfile::isLocalKey("diagrameditor/Xgrid"));
QVERIFY(!ConfigProfile::isLocalKey("shortcuts/mainwindow.fullscreen"));
@@ -31,6 +33,7 @@ private slots:
live.setValue("lang", "de");
live.setValue("diagrameditor/geometry", QByteArray("xyz"));
live.setValue("projects-recentfiles/file1", "/home/a/b.qet");
live.setValue("dialoggeometry/ConfigDialog", QByteArray("xyz"));
QSettings file(path("profile1.conf"), QSettings::IniFormat);
QCOMPARE(ConfigProfile::exportTo(live, file), 2);
@@ -38,6 +41,7 @@ private slots:
QCOMPARE(file.value("diagrameditor/Xgrid").toInt(), 7);
QVERIFY(!file.contains("diagrameditor/geometry"));
QVERIFY(!file.contains("projects-recentfiles/file1"));
QVERIFY(!file.contains("dialoggeometry/ConfigDialog"));
}
// Import replaces every setting, removes the ones the profile does not
@@ -87,6 +91,134 @@ private slots:
QCOMPARE(b.value(k), a.value(k));
}
// Every key belongs to one part; keys nobody listed are Other.
void partOfKeys()
{
using P = ConfigProfile::Part;
QCOMPARE(ConfigProfile::partOf("shortcuts/mainwindow.fullscreen"), P::Controls);
QCOMPARE(ConfigProfile::partOf("toolbars/icon_size"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/toolbars/diagram"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/custom_toolbars/names"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/shortcut_bar/canvas"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/gestures/directions"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/mouse_gestures"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/context_toolbar"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagramview/gestures"), P::Controls);
QCOMPARE(ConfigProfile::partOf("diagrameditor/defaultconductortype"), P::NewProject);
QCOMPARE(ConfigProfile::partOf("diagrameditor/defaultreportlabel"), P::NewProject);
QCOMPARE(ConfigProfile::partOf("diagrameditor/defaultxrefcoil"), P::NewProject);
QCOMPARE(ConfigProfile::partOf("diagrameditor/defaultguides/1/position"), P::NewProject);
QCOMPARE(ConfigProfile::partOf("autonum/conductor/current"), P::NewProject);
QCOMPARE(ConfigProfile::partOf("elements-collections/custom-collection-path"), P::Folders);
QCOMPARE(ConfigProfile::partOf("elements-collections/macros-path"), P::Folders);
QCOMPARE(ConfigProfile::partOf("diagrameditor/Xgrid"), P::Other);
QCOMPARE(ConfigProfile::partOf("diagrameditor/auto_break_conductor"), P::Other);
QCOMPARE(ConfigProfile::partOf("lang"), P::Other);
QCOMPARE(ConfigProfile::partOf("customColors"), P::Other);
}
// What the New project page writes for the folio size is the
// NewProject part, whatever key names BorderProperties uses.
void folioDefaultsAreNewProject()
{
QSettings live(path("live_border.conf"), QSettings::IniFormat);
BorderProperties().toSettings(live, "diagrameditor/default");
const QStringList keys = live.allKeys();
QVERIFY(!keys.isEmpty());
for (const QString &key : keys)
QCOMPARE(ConfigProfile::partOf(key), ConfigProfile::Part::NewProject);
}
// A file of some parts holds only their keys, never the folders, and
// is format 2 so that an older QElectroTech refuses it.
void exportSomeParts()
{
QSettings live(path("live4.conf"), QSettings::IniFormat);
live.setValue("shortcuts/mainwindow.fullscreen", "F11");
live.setValue("diagrameditor/defaultconductortype", "Multi");
live.setValue("diagrameditor/Xgrid", 7);
live.setValue("elements-collections/custom-collection-path", "/home/a/sym");
QSettings file(path("profile4.conf"), QSettings::IniFormat);
QCOMPARE(ConfigProfile::exportTo(live, file, {ConfigProfile::Part::NewProject}), 1);
QCOMPARE(file.value(ConfigProfile::marker_key).toInt(), 2);
QVERIFY(ConfigProfile::isProfile(file));
QCOMPARE(ConfigProfile::partsOf(file), QList<ConfigProfile::Part>{ConfigProfile::Part::NewProject});
QVERIFY(file.contains("diagrameditor/defaultconductortype"));
QVERIFY(!file.contains("shortcuts/mainwindow.fullscreen"));
QVERIFY(!file.contains("diagrameditor/Xgrid"));
QVERIFY(!file.contains("elements-collections/custom-collection-path"));
//Other without the two others: still no folders
QSettings file2(path("profile4b.conf"), QSettings::IniFormat);
ConfigProfile::exportTo(live, file2, {ConfigProfile::Part::Other});
QVERIFY(file2.contains("diagrameditor/Xgrid"));
QVERIFY(!file2.contains("elements-collections/custom-collection-path"));
}
// Every choosable part is a complete profile: format 1, folders
// included, readable by the QElectroTech that only knows format 1.
void exportEveryPartIsComplete()
{
QSettings live(path("live5.conf"), QSettings::IniFormat);
live.setValue("diagrameditor/Xgrid", 7);
live.setValue("elements-collections/custom-collection-path", "/home/a/sym");
QSettings file(path("profile5.conf"), QSettings::IniFormat);
ConfigProfile::exportTo(live, file, ConfigProfile::choosableParts());
QCOMPARE(file.value(ConfigProfile::marker_key).toInt(), 1);
QVERIFY(!file.contains(ConfigProfile::parts_key));
QVERIFY(file.contains("elements-collections/custom-collection-path"));
QCOMPARE(ConfigProfile::partsOf(file).size(), 4);
}
// Loading some parts replaces those parts only, removes their keys the
// file lacks, and keeps every other setting, folders included.
void importSomePartsKeepsTheRest()
{
QSettings file(path("profile6.conf"), QSettings::IniFormat);
file.setValue("diagrameditor/defaultconductortype", "Single");
file.setValue("diagrameditor/Xgrid", 99); // not in its parts: ignored
file.setValue(ConfigProfile::marker_key, 2);
file.setValue(ConfigProfile::parts_key, "newproject");
QSettings live(path("live6.conf"), QSettings::IniFormat);
live.setValue("diagrameditor/defaultconductortype", "Multi");
live.setValue("autonum/folio/current", "mine");
live.setValue("diagrameditor/Xgrid", 10);
live.setValue("shortcuts/mainwindow.fullscreen", "F11");
live.setValue("elements-collections/custom-collection-path", "/home/me/sym");
ConfigProfile::importFrom(file, live);
QCOMPARE(live.value("diagrameditor/defaultconductortype").toString(), QString("Single"));
QVERIFY(!live.contains("autonum/folio/current"));
QCOMPARE(live.value("diagrameditor/Xgrid").toInt(), 10);
QCOMPARE(live.value("shortcuts/mainwindow.fullscreen").toString(), QString("F11"));
QCOMPARE(live.value("elements-collections/custom-collection-path").toString(),
QString("/home/me/sym"));
QVERIFY(!live.contains(ConfigProfile::parts_key));
}
void restartOnlyWhenNeeded()
{
using P = ConfigProfile::Part;
QVERIFY(!ConfigProfile::needsRestart({P::NewProject}));
QVERIFY(ConfigProfile::needsRestart({P::NewProject, P::Controls}));
QVERIFY(ConfigProfile::needsRestart({P::Other}));
}
// A file of format 2 naming no known part is refused by the caller.
void unknownPartsGiveNothing()
{
QSettings file(path("profile7.conf"), QSettings::IniFormat);
file.setValue(ConfigProfile::marker_key, 2);
file.setValue(ConfigProfile::parts_key, "colours");
QVERIFY(ConfigProfile::partsOf(file).isEmpty());
}
void plainFileIsNotAProfile()
{
QSettings other(path("other.conf"), QSettings::IniFormat);