| 1099 | } |
| 1100 | |
| 1101 | void RenderingController::HandleGET_stdmultiWindow(const httplib::Request& req, httplib::Response& res) const |
| 1102 | { |
| 1103 | const auto id = ReadRequiredPathParam(req, "id"); |
| 1104 | |
| 1105 | if (!IsValidStdMultiWindowId(id)) |
| 1106 | { |
| 1107 | const auto error = ErrorResponse::RenderWindowNotFound(id, req.path); |
| 1108 | this->SendErrorResponse(res, 404, error); |
| 1109 | return; |
| 1110 | } |
| 1111 | |
| 1112 | // Compose summary locally; the bridge already exposes enough state via the |
| 1113 | // windows-list provider, and no per-window "summary" callback is needed. |
| 1114 | if (m_RenderWindowBridge == nullptr || !m_RenderWindowBridge->HasStdMultiWindowListProvider()) |
| 1115 | { |
| 1116 | const auto error = ErrorResponse::RenderWindowNotAvailable(req.path); |
| 1117 | this->SendErrorResponse(res, 503, error); |
| 1118 | return; |
| 1119 | } |
| 1120 | |
| 1121 | std::vector<WindowInfo> windows; |
| 1122 | try |
| 1123 | { |
| 1124 | windows = m_RenderWindowBridge->ListStdMultiWindows(); |
| 1125 | } |
| 1126 | catch (const std::exception& e) |
| 1127 | { |
| 1128 | const auto [status, payload] = MapBridgeException(e, req.path); |
| 1129 | this->SendErrorResponse(res, status, payload); |
| 1130 | return; |
| 1131 | } |
| 1132 | |
| 1133 | // The controller-side id validation already accepts only canonical ids, |
| 1134 | // so an empty window list at this point means the editor reports no windows |
| 1135 | // -- that is an editor state we also surface as RENDER_WINDOW_NOT_FOUND. |
| 1136 | // TODO(v3): replace the O(n) scan with a per-window descriptor query once |
| 1137 | // the bridge surface exposes a GetStdMultiWindowDescriptor(id) callback. |
| 1138 | // Tracked alongside the v3 migration checklist in |
| 1139 | // QmitkRestApiBridgeBindings.cpp; acceptable at v1.2 scale (<=4 slots). |
| 1140 | const auto matched = std::find_if(windows.begin(), windows.end(), |
| 1141 | [&](const WindowInfo& w) { return w.id == id; }); |
| 1142 | if (matched == windows.end()) |
| 1143 | { |
| 1144 | const auto error = ErrorResponse::RenderWindowNotFound(id, req.path); |
| 1145 | this->SendErrorResponse(res, 404, error); |
| 1146 | return; |
| 1147 | } |
| 1148 | |
| 1149 | const bool is3d = IsStdMulti3dWindow(id); |
| 1150 | |
| 1151 | nlohmann::json j; |
| 1152 | j["id"] = id; |
| 1153 | j["kind"] = is3d ? "3d" : "2d"; |
| 1154 | if (matched->viewDirection.has_value()) |
| 1155 | j["view_direction"] = AnatomicalPlaneToV2String(*matched->viewDirection); |
| 1156 | j["has_camera"] = true; |
| 1157 | j["has_selected_slice"] = !is3d; |
| 1158 | |