Skip to content

Commit 5746b64

Browse files
committed
fix: Fix saving stringlist in Settings via script
We can't use a QVariant, as it does not support list. We have to take a QJSValue, and transform it in a QVariant ?!
1 parent 7576540 commit 5746b64

File tree

8 files changed

+79
-24
lines changed

8 files changed

+79
-24
lines changed

docs/API/knut/settings.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Knut
1717
| | Name |
1818
|-|-|
1919
|bool |**[hasValue](#hasValue)**(string path)|
20-
|variant |**[setValue](#setValue)**(string path, variant value)|
20+
|variant |**[setValue](#setValue)**(string path, var value)|
2121
|variant |**[value](#value)**(string path, variant defaultValue = null)|
2222

2323
## Detailed Description
@@ -42,7 +42,7 @@ Returns true if Knut is currently in a test, and false otherwise
4242

4343
Returns true if the project settings has a settings `path`.
4444

45-
#### <a name="setValue"></a>variant **setValue**(string path, variant value)
45+
#### <a name="setValue"></a>variant **setValue**(string path, var value)
4646

4747
Adds a new value `value` to the project settings at the given `path`. Returns `true` if the operation succeeded.
4848

src/core/settings.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,10 @@ QVariant Settings::value(QString path, const QVariant &defaultValue) const
175175
}
176176

177177
/*!
178-
* \qmlmethod variant Settings::setValue(string path, variant value)
178+
* \qmlmethod variant Settings::setValue(string path, var value)
179179
* Adds a new value `value` to the project settings at the given `path`. Returns `true` if the operation succeeded.
180180
*/
181-
bool Settings::setValue(QString path, const QVariant &value)
181+
bool Settings::setValue(QString path, const QJSValue &value)
182182
{
183183
LOG("Settings::setValue", path, value);
184184

@@ -190,34 +190,47 @@ bool Settings::setValue(QString path, const QVariant &value)
190190
if (!path.startsWith('/'))
191191
path.prepend('/');
192192

193-
auto jsonPath = nlohmann::json::json_pointer(path.toStdString());
194-
switch (static_cast<QMetaType::Type>(value.typeId())) {
193+
const auto jsonPath = nlohmann::json::json_pointer(path.toStdString());
194+
195+
const auto var = value.toVariant();
196+
197+
switch (static_cast<QMetaType::Type>(var.typeId())) {
195198
case QMetaType::Bool:
196-
m_settings[jsonPath] = value.toBool();
197-
m_projectSettings[jsonPath] = value.toBool();
199+
m_settings[jsonPath] = var.toBool();
200+
m_projectSettings[jsonPath] = var.toBool();
198201
break;
199202
case QMetaType::Int:
200203
case QMetaType::LongLong:
201-
m_settings[jsonPath] = value.toInt();
202-
m_projectSettings[jsonPath] = value.toInt();
204+
m_settings[jsonPath] = var.toInt();
205+
m_projectSettings[jsonPath] = var.toInt();
203206
break;
204207
case QMetaType::UInt:
205208
case QMetaType::ULongLong:
206-
m_settings[jsonPath] = value.toUInt();
207-
m_projectSettings[jsonPath] = value.toUInt();
209+
m_settings[jsonPath] = var.toUInt();
210+
m_projectSettings[jsonPath] = var.toUInt();
208211
break;
209212
case QMetaType::Double:
210-
m_settings[jsonPath] = value.toDouble();
211-
m_projectSettings[jsonPath] = value.toDouble();
213+
m_settings[jsonPath] = var.toDouble();
214+
m_projectSettings[jsonPath] = var.toDouble();
212215
break;
213216
case QMetaType::QString:
214-
m_settings[jsonPath] = value.toString();
217+
m_settings[jsonPath] = var.toString();
215218
m_projectSettings[jsonPath] = value.toString();
216219
break;
217220
case QMetaType::QStringList:
218-
m_settings[jsonPath] = value.toStringList();
219-
m_projectSettings[jsonPath] = value.toStringList();
221+
m_settings[jsonPath] = var.toStringList();
222+
m_projectSettings[jsonPath] = var.toStringList();
220223
break;
224+
case QMetaType::QVariantList: {
225+
// A stringlist from QML will have a QVariantList meta type
226+
const QStringList list = var.toStringList();
227+
if (list.size() == var.toList().size()) {
228+
m_settings[jsonPath] = list;
229+
m_projectSettings[jsonPath] = list;
230+
} else {
231+
spdlog::error("Settings::setValue {} in {} - only string lists are supported", value.toString(), path);
232+
}
233+
} break;
221234
default:
222235
spdlog::error("Settings::setValue {} in {} - value type not handled", value.toString(), path);
223236
return false;

src/core/settings.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "utils/json.h"
1515
#include "utils/log.h"
1616

17+
#include <QJSValue>
1718
#include <QObject>
1819
#include <QStringList>
1920
#include <QTimer>
@@ -110,7 +111,7 @@ class Settings : public QObject
110111
bool hasLsp() const;
111112

112113
public slots:
113-
bool setValue(QString path, const QVariant &value);
114+
bool setValue(QString path, const QJSValue &value);
114115

115116
signals:
116117
void settingsLoaded();

test_data/tst_settings.qml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ Script {
4545
verify(Settings.hasValue("/numbers"));
4646
compare(Settings.value("/numbers"), undefined);
4747
}
48+
4849
}

test_data/tst_settings/setValue/knut.json.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"rc": {
2929
"dialog_scalex": 2.0
3030
},
31+
"thisisabooltest": true,
32+
"thisisadoubletest": 3.5,
3133
"thisisanothertest": 10,
34+
"thisisastringtest": "test",
3235
"thisisatest": [
3336
"This",
3437
"is",

test_data/tst_settings_rw.qml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
This file is part of Knut.
3+
4+
SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
5+
6+
SPDX-License-Identifier: GPL-3.0-only
7+
8+
Contact KDAB at <[email protected]> for commercial licensing options.
9+
*/
10+
11+
import QtQuick
12+
import Knut
13+
14+
Script {
15+
// We want to test the writing of settings without any project, that's why it's in a different QML file
16+
function test_setSettings() {
17+
verify(Settings.setValue("/int_val", 10))
18+
compare(Settings.value("/int_val"), 10)
19+
20+
verify(Settings.setValue("double_val", 3.5))
21+
compare(Settings.value("double_val"), 3.5)
22+
23+
verify(Settings.setValue("boolean/val", true))
24+
compare(Settings.value("boolean/val"), true)
25+
26+
verify(Settings.setValue("/stringlistval", ["a", "b", "c"]))
27+
compare(Settings.value("/stringlistval"), ["a", "b", "c"])
28+
}
29+
30+
}

tests/tst_knut.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class TestKnut : public QObject
7676

7777
private slots:
7878
KNUT_TEST(settings)
79+
KNUT_TEST(settings_rw)
7980
KNUT_TEST(dir)
8081
KNUT_TEST(fileinfo)
8182
KNUT_TEST(utils)

tests/tst_settings.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,21 @@ private slots:
9797
settings.setValue("/thisisatest", test);
9898
QCOMPARE(settings.value<QStringList>("/thisisatest"), test);
9999

100-
QVariant var(10);
101-
settings.setValue("/thisisanothertest", var);
100+
QJSValue varInt(10);
101+
settings.setValue("/thisisanothertest", varInt);
102102
QCOMPARE(settings.value("/thisisanothertest").toInt(), 10);
103103

104-
QVariant v;
105-
QVERIFY(!settings.setValue("/shouldnotwork", v));
104+
QJSValue varString("test");
105+
settings.setValue("/thisisastringtest", varString);
106+
QCOMPARE(settings.value("/thisisastringtest").toString(), "test");
106107

107-
QRect r;
108-
QVERIFY(!settings.setValue("/shouldnotwork", QVariant(r)));
108+
QJSValue varDouble(3.5);
109+
settings.setValue("/thisisadoubletest", varDouble);
110+
QCOMPARE(settings.value("/thisisadoubletest").toDouble(), 3.5);
111+
112+
QJSValue varBool(true);
113+
settings.setValue("/thisisabooltest", varBool);
114+
QCOMPARE(settings.value("/thisisabooltest").toBool(), true);
109115

110116
// There's only one signal, as the save is done asynchronously
111117
settingsSaved.wait();

0 commit comments

Comments
 (0)