134 lines
4.7 KiB
C++
134 lines
4.7 KiB
C++
/*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
#include "radialconfig.h"
|
|
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonParseError>
|
|
#include <QJsonValue>
|
|
|
|
namespace katecustom
|
|
{
|
|
|
|
namespace
|
|
{
|
|
// Recursively parse a slice node. A node with a non-empty "slices" array is a
|
|
// branch; otherwise it is a leaf bound to "action".
|
|
RadialNode parseNode(const QJsonObject &obj)
|
|
{
|
|
RadialNode node;
|
|
node.label = obj.value(QStringLiteral("label")).toString();
|
|
node.actionId = obj.value(QStringLiteral("action")).toString();
|
|
|
|
const QJsonArray slices = obj.value(QStringLiteral("slices")).toArray();
|
|
for (const QJsonValue &v : slices) {
|
|
if (v.isObject()) {
|
|
node.children.push_back(parseNode(v.toObject()));
|
|
}
|
|
}
|
|
// A branch must not also act as a leaf; the children take precedence.
|
|
if (!node.children.isEmpty()) {
|
|
node.actionId.clear();
|
|
}
|
|
return node;
|
|
}
|
|
} // namespace
|
|
|
|
QList<RadialDef> RadialConfig::fromJsonObject(const QJsonObject &obj)
|
|
{
|
|
QList<RadialDef> defs;
|
|
const QJsonArray radials = obj.value(QStringLiteral("radials")).toArray();
|
|
for (const QJsonValue &rv : radials) {
|
|
if (!rv.isObject()) {
|
|
continue;
|
|
}
|
|
const QJsonObject robj = rv.toObject();
|
|
|
|
RadialDef def;
|
|
def.name = robj.value(QStringLiteral("name")).toString();
|
|
def.trigger = robj.value(QStringLiteral("trigger")).toString();
|
|
def.mouseButton = robj.value(QStringLiteral("button")).toString();
|
|
|
|
const QJsonArray slices = robj.value(QStringLiteral("slices")).toArray();
|
|
for (const QJsonValue &sv : slices) {
|
|
if (sv.isObject()) {
|
|
def.root.children.push_back(parseNode(sv.toObject()));
|
|
}
|
|
}
|
|
|
|
// A radial with no slices is useless; skip it.
|
|
if (!def.root.children.isEmpty()) {
|
|
defs.push_back(def);
|
|
}
|
|
}
|
|
return defs;
|
|
}
|
|
|
|
QList<RadialDef> RadialConfig::fromJson(const QByteArray &json, QString *error)
|
|
{
|
|
QJsonParseError perr{};
|
|
const QJsonDocument doc = QJsonDocument::fromJson(json, &perr);
|
|
if (perr.error != QJsonParseError::NoError || !doc.isObject()) {
|
|
if (error) {
|
|
*error = perr.error != QJsonParseError::NoError
|
|
? perr.errorString()
|
|
: QStringLiteral("top-level JSON value is not an object");
|
|
}
|
|
return {};
|
|
}
|
|
return fromJsonObject(doc.object());
|
|
}
|
|
|
|
QList<RadialDef> RadialConfig::builtinDefault()
|
|
{
|
|
// One editing radial, triggered by Alt+R, built from common Kate actions.
|
|
// Leaf ids are Kate action objectNames; a trailing branch groups more.
|
|
auto leaf = [](const QString &label, const QString &action) {
|
|
RadialNode n;
|
|
n.label = label;
|
|
n.actionId = action;
|
|
return n;
|
|
};
|
|
|
|
RadialDef edit;
|
|
edit.name = QStringLiteral("edit");
|
|
edit.trigger = QStringLiteral("Alt+R");
|
|
edit.mouseButton = QStringLiteral("RightButton"); // natural radial gesture
|
|
|
|
// The radial holds actions that complete IN PLACE — no panel that pulls
|
|
// attention elsewhere. Panel-opening actions (Find, Replace) deliberately
|
|
// live in the command palette / keybinds instead, so the radial preserves
|
|
// editing flow. The "Command Palette…" slice is the escape hatch to those.
|
|
RadialNode more;
|
|
more.label = QStringLiteral("More");
|
|
more.children = {
|
|
leaf(QStringLiteral("Comment"), QStringLiteral("comment")),
|
|
leaf(QStringLiteral("Uncomment"), QStringLiteral("uncomment")),
|
|
leaf(QStringLiteral("Uppercase"), QStringLiteral("uppercase")),
|
|
leaf(QStringLiteral("Lowercase"), QStringLiteral("lowercase")),
|
|
leaf(QStringLiteral("Join Lines"), QStringLiteral("joinLines")),
|
|
// Opens the full command palette (handled specially by the plugin).
|
|
leaf(QStringLiteral("Command Palette…"), QStringLiteral("ollie_command_palette")),
|
|
};
|
|
|
|
edit.root.children = {
|
|
leaf(QStringLiteral("Cut"), QStringLiteral("edit_cut")),
|
|
leaf(QStringLiteral("Copy"), QStringLiteral("edit_copy")),
|
|
leaf(QStringLiteral("Paste"), QStringLiteral("edit_paste")),
|
|
leaf(QStringLiteral("Undo"), QStringLiteral("edit_undo")),
|
|
leaf(QStringLiteral("Redo"), QStringLiteral("edit_redo")),
|
|
// Multi-cursor on every selected line: a quintessential in-place action
|
|
// (select lines → gesture → keep typing). Referenced by visible text so
|
|
// it resolves regardless of the Kate action's objectName.
|
|
leaf(QStringLiteral("Cursors to Line Ends"),
|
|
QStringLiteral("Add Cursors to Line Ends")),
|
|
more,
|
|
};
|
|
|
|
return {edit};
|
|
}
|
|
|
|
} // namespace katecustom
|