QmlDesigner: Categorize slot actions

Task-number: QDS-8447
Change-Id: Ibc96bfcb7c87f0888e15f2533cab2567098a3760
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Aleksei German
2022-11-29 16:55:37 +01:00
parent aa69465ecf
commit 0c31cc475b

View File

@@ -487,11 +487,16 @@ QStringList getSignalsList(const ModelNode &node)
struct SlotEntry struct SlotEntry
{ {
QString category;
QString name; QString name;
std::function<void(SignalHandlerProperty)> action; std::function<void(SignalHandlerProperty)> action;
}; };
struct SlotList
{
QString categoryName;
QList<SlotEntry> slotEntries;
};
QList<ModelNode> stateGroups(const ModelNode &node) QList<ModelNode> stateGroups(const ModelNode &node)
{ {
if (!node.view()->isAttached()) if (!node.view()->isAttached())
@@ -502,13 +507,7 @@ QList<ModelNode> stateGroups(const ModelNode &node)
return node.view()->allModelNodesOfType(groupMetaInfo); return node.view()->allModelNodesOfType(groupMetaInfo);
} }
QStringList stateGroupsNames(const ModelNode &node) QList<SlotList> getSlotsLists(const ModelNode &node)
{
return Utils::transform(stateGroups(node),
[](const ModelNode &node) { return node.displayName(); });
}
QList<SlotEntry> getSlotsLists(const ModelNode &node)
{ {
if (!node.isValid()) if (!node.isValid())
return {}; return {};
@@ -516,58 +515,52 @@ QList<SlotEntry> getSlotsLists(const ModelNode &node)
if (!node.view()->rootModelNode().isValid()) if (!node.view()->rootModelNode().isValid())
return {}; return {};
QList<SlotEntry> resultList; QList<SlotList> resultList;
ModelNode rootNode = node.view()->rootModelNode(); ModelNode rootNode = node.view()->rootModelNode();
QmlObjectNode rootObjectNode(rootNode); QmlObjectNode rootObjectNode(rootNode);
const QString stateCategory = "Change State"; const QString changeStateStr = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Change State");
const QString changeStateGroupStr = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Change State Group");
const QString defaultStateStr = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Default State");
auto createStateChangeSlot =
[](const ModelNode &node, const QString &stateName, const QString &displayName) {
return SlotEntry({displayName, [node, stateName](SignalHandlerProperty signalHandler) {
signalHandler.setSource(
QString("%1.state = \"%2\"").arg(node.id(), stateName));
}});
};
//For now we are using category as part of the state name {
//We should change it, once we extend number of categories SlotList states = {changeStateStr, {}};
const SlotEntry defaultState = {stateCategory,
(stateCategory + " to " + "Default State"),
[rootNode](SignalHandlerProperty signalHandler) {
signalHandler.setSource(
QString("%1.state = \"\"").arg(rootNode.id()));
}};
resultList.push_back(defaultState);
for (const auto &stateName : rootObjectNode.states().names()) { const SlotEntry defaultState = createStateChangeSlot(rootNode, "", defaultStateStr);
SlotEntry entry = {stateCategory, states.slotEntries.push_back(defaultState);
(stateCategory + " to " + stateName),
[rootNode, stateName](SignalHandlerProperty signalHandler) {
signalHandler.setSource(
QString("%1.state = \"%2\"").arg(rootNode.id(), stateName));
}};
resultList.push_back(entry); for (const auto &stateName : rootObjectNode.states().names()) {
const SlotEntry entry = createStateChangeSlot(rootNode, stateName, stateName);
states.slotEntries.push_back(entry);
}
resultList.push_back(states);
} }
const auto sg = stateGroups(node); const QList<ModelNode> groups = stateGroups(node);
for (const auto &stateGroup : groups) {
for (const auto &stateGroup : sg) {
QmlObjectNode stateGroupObjectNode(stateGroup); QmlObjectNode stateGroupObjectNode(stateGroup);
const QString stateGroupCategory = QString("Change State Group") + " " SlotList stateGroupCategory = {changeStateGroupStr + " " + stateGroup.displayName(), {}};
+ stateGroup.displayName();
const SlotEntry defaultGroupState = {stateGroupCategory, const SlotEntry defaultGroupState = createStateChangeSlot(stateGroup, "", defaultStateStr);
(stateGroupCategory + " to " + "Default State"), stateGroupCategory.slotEntries.push_back(defaultGroupState);
[stateGroup](SignalHandlerProperty signalHandler) {
signalHandler.setSource(
QString("%1.state = \"\"").arg(stateGroup.id()));
}};
resultList.push_back(defaultGroupState);
for (const auto &stateName : stateGroupObjectNode.states().names()) { for (const auto &stateName : stateGroupObjectNode.states().names()) {
SlotEntry entry = {stateGroupCategory, const SlotEntry entry = createStateChangeSlot(stateGroup, stateName, stateName);
(stateGroupCategory + " to " + stateName), stateGroupCategory.slotEntries.push_back(entry);
[stateGroup, stateName](SignalHandlerProperty signalHandler) {
signalHandler.setSource(
QString("%1.state = \"%2\"").arg(stateGroup.id(), stateName));
}};
resultList.push_back(entry);
} }
resultList.push_back(stateGroupCategory);
} }
return resultList; return resultList;
@@ -577,10 +570,8 @@ QList<SlotEntry> getSlotsLists(const ModelNode &node)
ModelNode createNewConnection(ModelNode targetNode) ModelNode createNewConnection(ModelNode targetNode)
{ {
NodeMetaInfo connectionsMetaInfo = targetNode.view()->model()->metaInfo("QtQuick.Connections"); NodeMetaInfo connectionsMetaInfo = targetNode.view()->model()->metaInfo("QtQuick.Connections");
ModelNode newConnectionNode = targetNode.view() ModelNode newConnectionNode = targetNode.view()->createModelNode(
->createModelNode("QtQuick.Connections", "QtQuick.Connections", connectionsMetaInfo.majorVersion(), connectionsMetaInfo.minorVersion());
connectionsMetaInfo.majorVersion(),
connectionsMetaInfo.minorVersion());
if (QmlItemNode::isValidQmlItemNode(targetNode)) if (QmlItemNode::isValidQmlItemNode(targetNode))
targetNode.nodeAbstractProperty("data").reparentHere(newConnectionNode); targetNode.nodeAbstractProperty("data").reparentHere(newConnectionNode);
@@ -606,9 +597,7 @@ void removeSignal(SignalHandlerProperty signalHandler)
class ConnectionsModelNodeActionGroup : public ActionGroup class ConnectionsModelNodeActionGroup : public ActionGroup
{ {
public: public:
ConnectionsModelNodeActionGroup(const QString &displayName, ConnectionsModelNodeActionGroup(const QString &displayName, const QByteArray &menuId, int priority)
const QByteArray &menuId,
int priority)
: ActionGroup(displayName, : ActionGroup(displayName,
menuId, menuId,
priority, priority,
@@ -638,7 +627,7 @@ public:
QmlObjectNode currentObjectNode(currentNode); QmlObjectNode currentObjectNode(currentNode);
QStringList signalsList = getSignalsList(currentNode); QStringList signalsList = getSignalsList(currentNode);
QList<SlotEntry> slotsList = getSlotsLists(currentNode); QList<SlotList> slotsLists = getSlotsLists(currentNode);
if (!currentNode.hasId()) { if (!currentNode.hasId()) {
menu()->setEnabled(false); menu()->setEnabled(false);
@@ -654,7 +643,9 @@ public:
QMenu *activeSignalHandlerGroup = new QMenu(propertyName, menu()); QMenu *activeSignalHandlerGroup = new QMenu(propertyName, menu());
QMenu *editSignalGroup = new QMenu("Change Signal", menu()); QMenu *editSignalGroup = new QMenu(QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Change Signal"),
menu());
for (const auto &signalStr : signalsList) { for (const auto &signalStr : signalsList) {
if (prependSignal(signalStr).toUtf8() == signalHandler.name()) if (prependSignal(signalStr).toUtf8() == signalHandler.name())
@@ -680,40 +671,60 @@ public:
activeSignalHandlerGroup->addMenu(editSignalGroup); activeSignalHandlerGroup->addMenu(editSignalGroup);
if (!slotsList.isEmpty()) { if (!slotsLists.isEmpty()) {
QMenu *editSlotGroup = new QMenu("Change Slot", menu()); QMenu *editSlotGroup = new QMenu(QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Change Slot"),
menu());
for (const auto &slot : slotsList) { if (slotsLists.size() == 1) {
ActionTemplate *newSlotAction = new ActionTemplate( for (const auto &slot : slotsLists.at(0).slotEntries) {
(slot.name + "Id").toLatin1(), ActionTemplate *newSlotAction = new ActionTemplate(
slot.name, (slot.name + "Id").toLatin1(),
[slot, signalHandler](const SelectionContext &) { (slotsLists.at(0).categoryName
signalHandler.parentModelNode() + (QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
.view() " to ")) //context: Change State _to_ state1
->executeInTransaction("ConnectionsModelNodeActionGroup::" + slot.name),
"changeSlot", [slot, signalHandler](const SelectionContext &) {
[slot, signalHandler]() { signalHandler.parentModelNode().view()->executeInTransaction(
slot.action(signalHandler); "ConnectionsModelNodeActionGroup::"
}); "changeSlot",
}); [slot, signalHandler]() { slot.action(signalHandler); });
editSlotGroup->addAction(newSlotAction); });
editSlotGroup->addAction(newSlotAction);
}
} else {
for (const auto &slotCategory : slotsLists) {
QMenu *slotCategoryMenu = new QMenu(slotCategory.categoryName, menu());
for (const auto &slot : slotCategory.slotEntries) {
ActionTemplate *newSlotAction = new ActionTemplate(
(slot.name + "Id").toLatin1(),
slot.name,
[slot, signalHandler](const SelectionContext &) {
signalHandler.parentModelNode().view()->executeInTransaction(
"ConnectionsModelNodeActionGroup::"
"changeSlot",
[slot, signalHandler]() {
slot.action(signalHandler);
});
});
slotCategoryMenu->addAction(newSlotAction);
}
editSlotGroup->addMenu(slotCategoryMenu);
}
} }
activeSignalHandlerGroup->addMenu(editSlotGroup); activeSignalHandlerGroup->addMenu(editSlotGroup);
} }
ActionTemplate *openEditorAction = new ActionTemplate( ActionTemplate *openEditorAction = new ActionTemplate(
(propertyName + "OpenEditorId").toLatin1(), (propertyName + "OpenEditorId").toLatin1(),
QString( QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Connections Editor")),
QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Connections Editor")),
[=](const SelectionContext &) { [=](const SelectionContext &) {
signalHandler.parentModelNode() signalHandler.parentModelNode().view()->executeInTransaction(
.view() "ConnectionsModelNodeActionGroup::"
->executeInTransaction("ConnectionsModelNodeActionGroup::" "openConnectionsEditor",
"openConnectionsEditor", [signalHandler]() {
[signalHandler]() { ActionEditor::invokeEditor(signalHandler, removeSignal);
ActionEditor::invokeEditor(signalHandler, });
removeSignal);
});
}); });
activeSignalHandlerGroup->addAction(openEditorAction); activeSignalHandlerGroup->addAction(openEditorAction);
@@ -725,9 +736,7 @@ public:
signalHandler.parentModelNode().view()->executeInTransaction( signalHandler.parentModelNode().view()->executeInTransaction(
"ConnectionsModelNodeActionGroup::" "ConnectionsModelNodeActionGroup::"
"removeSignalHandler", "removeSignalHandler",
[signalHandler]() { [signalHandler]() { removeSignal(signalHandler); });
removeSignal(signalHandler);
});
}); });
activeSignalHandlerGroup->addAction(removeSignalHandlerAction); activeSignalHandlerGroup->addAction(removeSignalHandlerAction);
@@ -745,19 +754,46 @@ public:
for (const auto &signalStr : signalsList) { for (const auto &signalStr : signalsList) {
QMenu *newSignal = new QMenu(signalStr, addConnection); QMenu *newSignal = new QMenu(signalStr, addConnection);
for (const auto &slot : slotsList) { if (!slotsLists.isEmpty()) {
ActionTemplate *newSlot = new ActionTemplate( if (slotsLists.size() == 1) {
QString(signalStr + slot.name + "Id").toLatin1(), for (const auto &slot : slotsLists.at(0).slotEntries) {
slot.name, ActionTemplate *newSlot = new ActionTemplate(
[=](const SelectionContext &) { QString(signalStr + slot.name + "Id").toLatin1(),
currentNode.view()->executeInTransaction( (slotsLists.at(0).categoryName
"ConnectionsModelNodeActionGroup::addConnection", [=]() { + (QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
ModelNode newConnectionNode = createNewConnection(currentNode); " to ")) //context: Change State _to_ state1
slot.action(newConnectionNode.signalHandlerProperty( + slot.name),
prependSignal(signalStr).toLatin1())); [=](const SelectionContext &) {
currentNode.view()->executeInTransaction(
"ConnectionsModelNodeActionGroup::addConnection", [=]() {
ModelNode newConnectionNode = createNewConnection(currentNode);
slot.action(newConnectionNode.signalHandlerProperty(
prependSignal(signalStr).toLatin1()));
});
}); });
}); newSignal->addAction(newSlot);
newSignal->addAction(newSlot); }
} else {
for (const auto &slotCategory : slotsLists) {
QMenu *slotCategoryMenu = new QMenu(slotCategory.categoryName, menu());
for (const auto &slot : slotCategory.slotEntries) {
ActionTemplate *newSlot = new ActionTemplate(
QString(signalStr + slot.name + "Id").toLatin1(),
slot.name,
[=](const SelectionContext &) {
currentNode.view()->executeInTransaction(
"ConnectionsModelNodeActionGroup::addConnection", [=]() {
ModelNode newConnectionNode = createNewConnection(
currentNode);
slot.action(newConnectionNode.signalHandlerProperty(
prependSignal(signalStr).toLatin1()));
});
});
slotCategoryMenu->addAction(newSlot);
}
newSignal->addMenu(slotCategoryMenu);
}
}
} }
ActionTemplate *openEditorAction = new ActionTemplate( ActionTemplate *openEditorAction = new ActionTemplate(
@@ -770,9 +806,8 @@ public:
[=]() { [=]() {
ModelNode newConnectionNode = createNewConnection(currentNode); ModelNode newConnectionNode = createNewConnection(currentNode);
SignalHandlerProperty newHandler SignalHandlerProperty newHandler = newConnectionNode.signalHandlerProperty(
= newConnectionNode.signalHandlerProperty( prependSignal(signalStr).toLatin1());
prependSignal(signalStr).toLatin1());
newHandler.setSource( newHandler.setSource(
QString("console.log(\"%1.%2\")").arg(currentNode.id(), signalStr)); QString("console.log(\"%1.%2\")").arg(currentNode.id(), signalStr));