* @brief Reports or removes orphaned workspace widget refs. */
| 1327 | * @brief Reports or removes orphaned workspace widget refs. |
| 1328 | */ |
| 1329 | API::CommandResponse API::Handlers::WorkspacesHandler::cleanup(const QString& id, |
| 1330 | const QJsonObject& params) |
| 1331 | { |
| 1332 | const bool dryRun = params.value(QStringLiteral("dryRun")).toBool(false); |
| 1333 | if (!dryRun && !inProjectFileMode()) |
| 1334 | return CommandResponse::makeError( |
| 1335 | id, ErrorCode::InvalidParam, QStringLiteral("Workspace mutations require ProjectFile mode")); |
| 1336 | |
| 1337 | auto& pm = DataModel::ProjectModel::instance(); |
| 1338 | const auto& wsList = pm.editorWorkspaces(); |
| 1339 | const auto lookup = DataModel::ProjectEditor::buildResolvedWidgetLookup(pm); |
| 1340 | |
| 1341 | const bool filtered = params.contains(QStringLiteral("workspaceId")); |
| 1342 | const int onlyWid = filtered ? params.value(QStringLiteral("workspaceId")).toInt() : -1; |
| 1343 | |
| 1344 | QJsonArray removedRefs; |
| 1345 | for (const auto& ws : wsList) { |
| 1346 | if (filtered && ws.workspaceId != onlyWid) |
| 1347 | continue; |
| 1348 | |
| 1349 | for (const auto& ref : ws.widgetRefs) { |
| 1350 | const auto key = DataModel::ProjectEditor::workspaceWidgetKey( |
| 1351 | ref.widgetType, ref.groupUniqueId, ref.relativeIndex); |
| 1352 | if (lookup.contains(key)) |
| 1353 | continue; |
| 1354 | |
| 1355 | QJsonObject entry; |
| 1356 | entry[QStringLiteral("workspaceId")] = ws.workspaceId; |
| 1357 | entry[QStringLiteral("widgetType")] = ref.widgetType; |
| 1358 | entry[QStringLiteral("widgetTypeSlug")] = |
| 1359 | API::EnumLabels::dashboardWidgetSlug(ref.widgetType); |
| 1360 | entry[QStringLiteral("groupId")] = ref.groupUniqueId; |
| 1361 | entry[QStringLiteral("relativeIndex")] = ref.relativeIndex; |
| 1362 | entry[QStringLiteral("widgetId")] = |
| 1363 | widgetIdFor(ws.workspaceId, ref.widgetType, ref.groupUniqueId, ref.relativeIndex); |
| 1364 | removedRefs.append(entry); |
| 1365 | } |
| 1366 | } |
| 1367 | |
| 1368 | int removed = 0; |
| 1369 | if (!dryRun && !removedRefs.isEmpty()) { |
| 1370 | QSet<qint64> validKeys; |
| 1371 | validKeys.reserve(lookup.size()); |
| 1372 | for (auto it = lookup.constBegin(); it != lookup.constEnd(); ++it) |
| 1373 | validKeys.insert(it.key()); |
| 1374 | |
| 1375 | removed = pm.cleanupWorkspaceWidgetRefs(validKeys); |
| 1376 | } |
| 1377 | |
| 1378 | QJsonObject result; |
| 1379 | result[QStringLiteral("ok")] = true; |
| 1380 | result[QStringLiteral("dryRun")] = dryRun; |
| 1381 | result[QStringLiteral("removed")] = dryRun ? removedRefs.size() : removed; |
| 1382 | result[QStringLiteral("removedRefs")] = removedRefs; |
| 1383 | return CommandResponse::makeSuccess(id, result); |
| 1384 | } |
| 1385 | |
| 1386 | /** |
nothing calls this directly
no test coverage detected