* @brief Moves a group to a new position in the project. */
| 3602 | * @brief Moves a group to a new position in the project. |
| 3603 | */ |
| 3604 | API::CommandResponse API::Handlers::ProjectHandler::groupMove(const QString& id, |
| 3605 | const QJsonObject& params) |
| 3606 | { |
| 3607 | if (!params.contains(Keys::GroupId)) |
| 3608 | return CommandResponse::makeError( |
| 3609 | id, ErrorCode::MissingParam, QStringLiteral("Missing required parameter: groupId")); |
| 3610 | |
| 3611 | if (!params.contains(QStringLiteral("newPosition"))) |
| 3612 | return CommandResponse::makeError( |
| 3613 | id, ErrorCode::MissingParam, QStringLiteral("Missing required parameter: newPosition")); |
| 3614 | |
| 3615 | const int groupId = params.value(Keys::GroupId).toInt(); |
| 3616 | const int newPosition = params.value(QStringLiteral("newPosition")).toInt(); |
| 3617 | const bool isDryRun = params.value(QStringLiteral("dryRun")).toBool(false); |
| 3618 | |
| 3619 | auto& pm = DataModel::ProjectModel::instance(); |
| 3620 | const auto& groups = pm.groups(); |
| 3621 | if (groupId < 0 || groupId >= static_cast<int>(groups.size())) |
| 3622 | return CommandResponse::makeError( |
| 3623 | id, ErrorCode::InvalidParam, QStringLiteral("Group id out of range: %1").arg(groupId)); |
| 3624 | |
| 3625 | const int clampedNew = std::clamp(newPosition, 0, static_cast<int>(groups.size()) - 1); |
| 3626 | |
| 3627 | QJsonArray renumbered; |
| 3628 | for (const auto& g : groups) { |
| 3629 | const int newId = projectedAfterMove(g.groupId, groupId, clampedNew); |
| 3630 | if (newId == g.groupId) |
| 3631 | continue; |
| 3632 | |
| 3633 | QJsonObject row; |
| 3634 | row[QStringLiteral("oldGroupId")] = g.groupId; |
| 3635 | row[QStringLiteral("newGroupId")] = newId; |
| 3636 | row[QStringLiteral("title")] = g.title; |
| 3637 | row[QStringLiteral("datasetCount")] = static_cast<int>(g.datasets.size()); |
| 3638 | renumbered.append(row); |
| 3639 | } |
| 3640 | |
| 3641 | qint64 preEpoch = 0; |
| 3642 | if (!isDryRun) { |
| 3643 | preEpoch = captureProjectEpoch(); |
| 3644 | pm.moveGroup(groupId, newPosition); |
| 3645 | } |
| 3646 | |
| 3647 | QJsonObject result; |
| 3648 | if (isDryRun) |
| 3649 | result[QStringLiteral("dryRun")] = true; |
| 3650 | |
| 3651 | result[QStringLiteral("oldPosition")] = groupId; |
| 3652 | result[QStringLiteral("newPosition")] = clampedNew; |
| 3653 | result[QStringLiteral("moved")] = !isDryRun; |
| 3654 | result[QStringLiteral("renumbered")] = renumbered; |
| 3655 | |
| 3656 | QString warning; |
| 3657 | if (isDryRun) |
| 3658 | warning = QStringLiteral( |
| 3659 | "DRY RUN: no changes were written. Re-call without dryRun:true to commit. The " |
| 3660 | "renumbered[] array shows the new groupId for each affected group; uniqueIds stay " |
| 3661 | "stable across reorders."); |
nothing calls this directly
no test coverage detected