Skip to content

Commit 611f80c

Browse files
authored
feat: add a way to initialize script dialog from command line (#136)
Fixes #32 Tested in MR: https://codereview.kdab.com/c/kdab/mfc-utils/+/144788
1 parent e6e2f9d commit 611f80c

File tree

8 files changed

+78
-17
lines changed

8 files changed

+78
-17
lines changed

src/core/knutcore.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ bool KnutCore::process(const QStringList &arguments)
124124
}
125125
}
126126

127+
// Get json data if provided
128+
const QString jsonDataStr = parser.value("data");
129+
json jsonData;
130+
if (!jsonDataStr.isEmpty()) {
131+
try {
132+
jsonData = json::parse(jsonDataStr.toStdString());
133+
} catch (const json::parse_error &ex) {
134+
spdlog::error("JSON parsing error at byte {}: {}", ex.byte, ex.what());
135+
return false;
136+
}
137+
}
138+
127139
// Run the script passed in parameter, if any
128140
// Exit Knut if there are no windows opened
129141
auto scriptName = parser.value("run");
@@ -132,8 +144,8 @@ bool KnutCore::process(const QStringList &arguments)
132144
}
133145

134146
if (!scriptName.isEmpty()) {
135-
QTimer::singleShot(0, this, [scriptName]() {
136-
ScriptManager::instance()->runScript(scriptName);
147+
QTimer::singleShot(0, this, [scriptName, jsonData = std::move(jsonData)]() mutable {
148+
ScriptManager::instance()->runScript(scriptName, std::move(jsonData));
137149
});
138150
connect(
139151
ScriptManager::instance(), &ScriptManager::scriptFinished, qApp,
@@ -160,6 +172,7 @@ void KnutCore::initParser(QCommandLineParser &parser) const
160172
{{"i", "input"}, "Opens document <file> on startup.", "file"},
161173
{{"l", "line"}, "Line in the current file, if any.", "line"},
162174
{{"c", "column"}, "Column in the current file, if any.", "column"},
175+
{{"d", "data"}, "JSON data string for initializing the dialog.", "data"},
163176
{"json-list", "Returns the list of all available scripts as a JSON file"},
164177
{"json-settings", "Returns the settings as a JSON file"}});
165178
}

src/core/scriptdialogitem.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include <QDoubleSpinBox>
2525
#include <QFile>
2626
#include <QFileInfo>
27+
#include <QJsonDocument>
28+
#include <QJsonObject>
29+
#include <QJsonValue>
2730
#include <QLineEdit>
2831
#include <QMessageBox>
2932
#include <QPushButton>
@@ -145,6 +148,29 @@ ScriptDialogItem::ScriptDialogItem(QWidget *parent)
145148
});
146149
}
147150

151+
void ScriptDialogItem::initialize(nlohmann::json &&jsonData)
152+
{
153+
for (auto it = jsonData.cbegin(); it != jsonData.cend(); ++it) {
154+
const QString key = QString::fromStdString(it.key());
155+
156+
QVariant value;
157+
if (it.value().is_string()) {
158+
value = QString::fromStdString(it.value().get<std::string>());
159+
} else if (it.value().is_boolean()) {
160+
value = it.value().get<bool>();
161+
} else if (it.value().is_number_integer()) {
162+
value = it.value().get<int>();
163+
} else if (it.value().is_number_float()) {
164+
value = it.value().get<double>();
165+
} else {
166+
spdlog::error("Unsupported data type for key '{}'", it.key());
167+
value = QString::fromStdString(it.value().dump());
168+
}
169+
170+
changeValue(key, value);
171+
}
172+
}
173+
148174
void ScriptDialogItem::done(int code)
149175
{
150176
// When showing progress, the `onAccepted` handler will likely call `QCoreApplication::processEvents` multiple
@@ -535,18 +561,25 @@ void ScriptDialogItem::createProperties(QWidget *dialogWidget)
535561
void ScriptDialogItem::changeValue(const QString &key, const QVariant &value)
536562
{
537563
auto widget = findChild<QWidget *>(key);
564+
538565
if (auto lineEdit = qobject_cast<QLineEdit *>(widget)) {
539566
lineEdit->setText(value.toString());
567+
return;
540568
} else if (auto checkBox = qobject_cast<QCheckBox *>(widget)) {
541569
checkBox->setChecked(value.toBool());
570+
return;
542571
} else if (auto radioButton = qobject_cast<QRadioButton *>(widget)) {
543572
radioButton->setChecked(value.toBool());
573+
return;
544574
} else if (auto spinBox = qobject_cast<QSpinBox *>(widget)) {
545575
spinBox->setValue(value.toInt());
576+
return;
546577
} else if (auto doubleSpinBox = qobject_cast<QDoubleSpinBox *>(widget)) {
547578
doubleSpinBox->setValue(value.toDouble());
579+
return;
548580
} else if (auto comboBox = qobject_cast<QComboBox *>(widget)) {
549581
comboBox->setCurrentText(value.toString());
582+
return;
550583
}
551584

552585
// It may be a combobox model
@@ -557,6 +590,14 @@ void ScriptDialogItem::changeValue(const QString &key, const QVariant &value)
557590
if (comboBox->count())
558591
comboBox->setCurrentIndex(0);
559592
}
593+
return;
594+
}
595+
596+
if (!widget) {
597+
spdlog::warn("No widget found for the key '{}'.", key.toStdString());
598+
} else {
599+
spdlog::warn("Unsupported widget type '{}' for the key '{}'.", widget->metaObject()->className(),
600+
key.toStdString());
560601
}
561602
}
562603

src/core/scriptdialogitem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <QJSValue>
1515
#include <QQmlListProperty>
1616
#include <QQmlPropertyMap>
17+
#include <nlohmann/json_fwd.hpp>
1718
#include <vector>
1819

1920
class ScriptProgressDialog;
@@ -35,6 +36,8 @@ class ScriptDialogItem : public QDialog
3536
public:
3637
explicit ScriptDialogItem(QWidget *parent = nullptr);
3738

39+
void initialize(nlohmann::json &&jsonData);
40+
3841
QObject *data() const;
3942
QQmlListProperty<QObject> childrenData();
4043

src/core/scriptmanager.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ QAbstractItemModel *ScriptManager::model()
7777
return model;
7878
}
7979

80-
void ScriptManager::runScript(const QString &fileName, bool async, bool log)
80+
void ScriptManager::runScript(const QString &fileName, nlohmann::json &&data, bool async, bool log)
8181
{
8282
if (log)
8383
spdlog::debug("==> Start script {}", fileName);
@@ -88,11 +88,11 @@ void ScriptManager::runScript(const QString &fileName, bool async, bool log)
8888
};
8989

9090
if (async)
91-
QTimer::singleShot(0, this, [this, fileName, endScriptCallback]() {
92-
doRunScript(fileName, endScriptCallback);
91+
QTimer::singleShot(0, this, [this, fileName, data = std::move(data), endScriptCallback]() mutable {
92+
doRunScript(fileName, std::move(data), endScriptCallback);
9393
});
9494
else
95-
doRunScript(fileName, endScriptCallback);
95+
doRunScript(fileName, std::move(data), endScriptCallback);
9696
}
9797

9898
void ScriptManager::addScript(const QString &fileName)
@@ -199,9 +199,9 @@ ScriptManager::ScriptList::iterator ScriptManager::removeScript(const ScriptList
199199
return it;
200200
}
201201

202-
void ScriptManager::doRunScript(const QString &fileName, const std::function<void()> &endFunc)
202+
void ScriptManager::doRunScript(const QString &fileName, nlohmann::json &&data, const std::function<void()> &endFunc)
203203
{
204-
m_result = m_runner->runScript(fileName, endFunc);
204+
m_result = m_runner->runScript(fileName, std::move(data), endFunc);
205205
if (m_runner->hasError()) {
206206
const auto errors = m_runner->errors();
207207
for (const auto &error : errors)

src/core/scriptmanager.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <QStringList>
1515
#include <QVariant>
1616
#include <functional>
17+
#include <nlohmann/json.hpp>
1718
#include <vector>
1819

1920
class QFileSystemWatcher;
@@ -57,8 +58,8 @@ class ScriptManager : public QObject
5758

5859
static QAbstractItemModel *model();
5960

60-
public slots:
61-
void runScript(const QString &fileName, bool async = true, bool log = true);
61+
void runScript(const QString &fileName, nlohmann::json &&data = nlohmann::json::object(), bool async = true,
62+
bool log = true);
6263

6364
signals:
6465
void scriptFinished(const QVariant &result);
@@ -79,7 +80,7 @@ public slots:
7980
void addScriptsFromPath(const QString &path);
8081
void removeScriptsFromPath(const QString &path);
8182

82-
void doRunScript(const QString &fileName, const std::function<void()> &endFunc);
83+
void doRunScript(const QString &fileName, nlohmann::json &&data, const std::function<void()> &endFunc);
8384

8485
void updateDirectories();
8586
void updateScriptDirectory(const QString &path);

src/core/scriptrunner.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ ScriptRunner::ScriptRunner(QObject *parent)
171171

172172
ScriptRunner::~ScriptRunner() = default;
173173

174-
QVariant ScriptRunner::runScript(const QString &fileName, const std::function<void()> &endCallback)
174+
QVariant ScriptRunner::runScript(const QString &fileName, nlohmann::json &&data,
175+
const std::function<void()> &endCallback)
175176
{
176177
const QFileInfo fi(fileName);
177178

@@ -191,7 +192,7 @@ QVariant ScriptRunner::runScript(const QString &fileName, const std::function<vo
191192
if (fi.suffix() == "js") {
192193
result = runJavascript(fullName, engine);
193194
} else {
194-
result = runQml(fullName, engine);
195+
result = runQml(fullName, std::move(data), engine);
195196
}
196197
// engine is deleted in runJavascript or runQml
197198
} else {
@@ -312,7 +313,7 @@ QVariant ScriptRunner::runJavascript(const QString &fileName, QQmlEngine *engine
312313
return QVariant(ErrorCode);
313314
}
314315

315-
QVariant ScriptRunner::runQml(const QString &fileName, QQmlEngine *engine)
316+
QVariant ScriptRunner::runQml(const QString &fileName, nlohmann::json &&data, QQmlEngine *engine)
316317
{
317318
auto component = new QQmlComponent(engine, engine);
318319
component->loadUrl(QUrl::fromLocalFile(fileName));
@@ -346,6 +347,7 @@ QVariant ScriptRunner::runQml(const QString &fileName, QQmlEngine *engine)
346347
window->show();
347348
} else if (auto dialog = qobject_cast<ScriptDialogItem *>(topLevel)) {
348349
engine->setProperty("scriptWindow", true);
350+
dialog->initialize(std::move(data));
349351
dialog->show();
350352
connect(dialog, &ScriptDialogItem::scriptFinished, engine, &QObject::deleteLater);
351353
}

src/core/scriptrunner.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <QSharedPointer>
1818
#include <QString>
1919
#include <functional>
20+
#include <nlohmann/json.hpp>
2021

2122
namespace Core {
2223

@@ -36,7 +37,7 @@ class ScriptRunner : public QObject
3637

3738
// Run a script
3839
using EndScriptFunc = std::function<void()>;
39-
QVariant runScript(const QString &fileName, const EndScriptFunc &endCallback = {});
40+
QVariant runScript(const QString &fileName, nlohmann::json &&data, const EndScriptFunc &endCallback = {});
4041

4142
bool hasError() const { return m_hasError; }
4243
QList<QQmlError> errors() const { return m_errors; }
@@ -52,7 +53,7 @@ class ScriptRunner : public QObject
5253
private:
5354
QQmlEngine *getEngine(const QString &fileName);
5455
QVariant runJavascript(const QString &fileName, QQmlEngine *engine);
55-
QVariant runQml(const QString &fileName, QQmlEngine *engine);
56+
QVariant runQml(const QString &fileName, nlohmann::json &&data, QQmlEngine *engine);
5657
void filterErrors(const QQmlComponent &component);
5758

5859
private:

src/core/utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void Utils::runScript(const QString &path, bool log)
111111
LOG("Utils::runScript", LOG_ARG("path", path), log);
112112

113113
// Run the script synchronously
114-
ScriptManager::instance()->runScript(path, false, log);
114+
ScriptManager::instance()->runScript(path, nlohmann::json::object(), false, log);
115115
}
116116

117117
/*!

0 commit comments

Comments
 (0)