# HG changeset patch # User am@osimis.io # Date 1538728696 -7200 # Node ID aad37d0b64077fcc03e32bfd09e8f772f197fac2 # Parent 97f16214dc5ef7767cfdf76d7173e53ce003b887 Added LayerWidget::RemoveLayer + DELETE commands in WebService diff -r 97f16214dc5e -r aad37d0b6407 Framework/Messages/MessageType.h --- a/Framework/Messages/MessageType.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Messages/MessageType.h Fri Oct 05 10:38:16 2018 +0200 @@ -47,9 +47,7 @@ MessageType_OrthancApi_GenericGetJson_Ready, MessageType_OrthancApi_GenericGetBinary_Ready, MessageType_OrthancApi_GenericHttpError_Ready, - MessageType_OrthancApi_GetStudyIds_Ready, - MessageType_OrthancApi_GetStudy_Ready, - MessageType_OrthancApi_GetSeries_Ready, + MessageType_OrthancApi_GenericEmptyResponse_Ready, // used in unit tests only MessageType_Test1, diff -r 97f16214dc5e -r aad37d0b6407 Framework/Toolbox/IWebService.h --- a/Framework/Toolbox/IWebService.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Toolbox/IWebService.h Fri Oct 05 10:38:16 2018 +0200 @@ -97,5 +97,11 @@ MessageHandler* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; + virtual void DeleteAsync(const std::string& uri, + const Headers& headers, + Orthanc::IDynamicObject* payload, + MessageHandler* successCallback, + MessageHandler* failureCallback = NULL, + unsigned int timeoutInSeconds = 60) = 0; }; } diff -r 97f16214dc5e -r aad37d0b6407 Framework/Toolbox/OrthancApiClient.cpp --- a/Framework/Toolbox/OrthancApiClient.cpp Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Toolbox/OrthancApiClient.cpp Fri Oct 05 10:38:16 2018 +0200 @@ -120,6 +120,49 @@ } }; + // performs the translation between IWebService messages and OrthancApiClient messages + // TODO: handle destruction of this object (with shared_ptr ?::delete_later ???) + class HttpResponseToEmptyConverter : public IObserver, IObservable + { + std::auto_ptr> orthancApiSuccessCallback_; + std::auto_ptr> orthancApiFailureCallback_; + public: + HttpResponseToEmptyConverter(MessageBroker& broker, + MessageHandler* orthancApiSuccessCallback, + MessageHandler* orthancApiFailureCallback) + : IObserver(broker), + IObservable(broker), + orthancApiSuccessCallback_(orthancApiSuccessCallback), + orthancApiFailureCallback_(orthancApiFailureCallback) + { + } + + void ConvertResponseToEmpty(const IWebService::HttpRequestSuccessMessage& message) + { + if (orthancApiSuccessCallback_.get() != NULL) + { + orthancApiSuccessCallback_->Apply(OrthancApiClient::EmptyResponseReadyMessage(message.uri_, message.payload_)); + } + else if (orthancApiFailureCallback_.get() != NULL) + { + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_, message.payload_)); + } + + delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) + } + + void ConvertError(const IWebService::HttpRequestErrorMessage& message) + { + if (orthancApiFailureCallback_.get() != NULL) + { + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_)); + } + + delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) + } + }; + + void OrthancApiClient::GetJsonAsync(const std::string& uri, MessageHandler* successCallback, MessageHandler* failureCallback, @@ -168,5 +211,16 @@ return PostBinaryAsyncExpectJson(uri, body, successCallback, failureCallback, payload); } + void OrthancApiClient::DeleteAsync(const std::string& uri, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) + { + HttpResponseToEmptyConverter* converter = new HttpResponseToEmptyConverter(broker_, successCallback, failureCallback); // it is currently deleting itself after being used + orthanc_.DeleteAsync(uri, IWebService::Headers(), payload, + new Callable(*converter, &HttpResponseToEmptyConverter::ConvertResponseToEmpty), + new Callable(*converter, &HttpResponseToEmptyConverter::ConvertError)); + } + } diff -r 97f16214dc5e -r aad37d0b6407 Framework/Toolbox/OrthancApiClient.h --- a/Framework/Toolbox/OrthancApiClient.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Toolbox/OrthancApiClient.h Fri Oct 05 10:38:16 2018 +0200 @@ -52,6 +52,20 @@ } }; + struct EmptyResponseReadyMessage : public BaseMessage + { + std::string Uri; + Orthanc::IDynamicObject* Payload; + + EmptyResponseReadyMessage(const std::string& uri, + Orthanc::IDynamicObject* payload = NULL) + : BaseMessage(), + Uri(uri), + Payload(payload) + { + } + }; + struct HttpErrorMessage : public BaseMessage { std::string Uri; @@ -142,5 +156,12 @@ MessageHandler* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL); + // schedule a DELETE request expecting an empty response. + void DeleteAsync(const std::string& uri, + MessageHandler* successCallback, + MessageHandler* failureCallback = NULL, + Orthanc::IDynamicObject* payload = NULL); + + }; } diff -r 97f16214dc5e -r aad37d0b6407 Framework/Widgets/LayerWidget.cpp --- a/Framework/Widgets/LayerWidget.cpp Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Widgets/LayerWidget.cpp Fri Oct 05 10:38:16 2018 +0200 @@ -37,7 +37,7 @@ double thickness_; size_t countMissing_; std::vector renderers_; - +public: void DeleteLayer(size_t index) { if (index >= renderers_.size()) @@ -56,7 +56,6 @@ } } - public: Scene(const CoordinateSystem3D& slice, double thickness, size_t countLayers) : @@ -365,15 +364,6 @@ IObservable(broker), started_(false) { -// DeclareHandledMessage(MessageType_LayerSource_GeometryReady); -// DeclareHandledMessage(MessageType_LayerSource_ContentChanged); -// DeclareHandledMessage(MessageType_LayerSource_LayerReady); -// DeclareHandledMessage(MessageType_LayerSource_SliceChanged); -// DeclareHandledMessage(MessageType_LayerSource_GeometryError); - -// DeclareEmittableMessage(MessageType_Widget_GeometryChanged); -// DeclareEmittableMessage(MessageType_Widget_ContentChanged); - SetBackgroundCleared(true); } @@ -440,6 +430,26 @@ InvalidateLayer(index); } + void LayerWidget::RemoveLayer(size_t index) + { + if (index >= layers_.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + ILayerSource* previousLayer = layers_[index]; + layersIndex_.erase(layersIndex_.find(previousLayer)); + layers_.erase(layers_.begin() + index); + changedLayers_.erase(changedLayers_.begin() + index); + styles_.erase(styles_.begin() + index); + + delete layers_[index]; + + currentScene_->DeleteLayer(index); + ResetPendingScene(); + + NotifyContentChanged(); + } const RenderStyle& LayerWidget::GetLayerStyle(size_t layer) const { diff -r 97f16214dc5e -r aad37d0b6407 Framework/Widgets/LayerWidget.h --- a/Framework/Widgets/LayerWidget.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Framework/Widgets/LayerWidget.h Fri Oct 05 10:38:16 2018 +0200 @@ -97,6 +97,8 @@ void ReplaceLayer(size_t layerIndex, ILayerSource* layer); // Takes ownership + void RemoveLayer(size_t layerIndex); + size_t GetLayerCount() const { return layers_.size(); diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Generic/OracleWebService.h --- a/Platforms/Generic/OracleWebService.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Platforms/Generic/OracleWebService.h Fri Oct 05 10:38:16 2018 +0200 @@ -25,6 +25,7 @@ #include "Oracle.h" #include "WebServiceGetCommand.h" #include "WebServicePostCommand.h" +#include "WebServiceDeleteCommand.h" #include "../../Applications/Generic/NativeStoneApplicationContext.h" namespace OrthancStone @@ -72,6 +73,17 @@ oracle_.Submit(new WebServicePostCommand(broker_, successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, body, payload, context_)); } + virtual void DeleteAsync(const std::string& uri, + const Headers& headers, + Orthanc::IDynamicObject* payload, + MessageHandler* successCallback, + MessageHandler* failureCallback = NULL, + unsigned int timeoutInSeconds = 60) + { + oracle_.Submit(new WebServiceDeleteCommand(broker_, successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); + } + + void Start() { oracle_.Start(); diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Generic/WebServiceDeleteCommand.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/Generic/WebServiceDeleteCommand.cpp Fri Oct 05 10:38:16 2018 +0200 @@ -0,0 +1,55 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "WebServiceDeleteCommand.h" + +#include + +namespace OrthancStone +{ + WebServiceDeleteCommand::WebServiceDeleteCommand(MessageBroker& broker, + MessageHandler* successCallback, // takes ownership + MessageHandler* failureCallback, // takes ownership + const Orthanc::WebServiceParameters& parameters, + const std::string& uri, + const IWebService::Headers& headers, + unsigned int timeoutInSeconds, + Orthanc::IDynamicObject* payload /* takes ownership */, + NativeStoneApplicationContext& context) : + WebServiceCommandBase(broker, successCallback, failureCallback, parameters, uri, headers, timeoutInSeconds, payload, context) + { + } + + void WebServiceDeleteCommand::Execute() + { + Orthanc::HttpClient client(parameters_, uri_); + client.SetTimeout(timeoutInSeconds_); + client.SetMethod(Orthanc::HttpMethod_Delete); + + for (IWebService::Headers::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + { + client.AddHeader(it->first, it->second); + } + + success_ = client.Apply(answer_); + } + +} diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Generic/WebServiceDeleteCommand.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/Generic/WebServiceDeleteCommand.h Fri Oct 05 10:38:16 2018 +0200 @@ -0,0 +1,43 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "WebServiceCommandBase.h" + +namespace OrthancStone +{ + class WebServiceDeleteCommand : public WebServiceCommandBase + { + public: + WebServiceDeleteCommand(MessageBroker& broker, + MessageHandler* successCallback, // takes ownership + MessageHandler* failureCallback, // takes ownership + const Orthanc::WebServiceParameters& parameters, + const std::string& uri, + const IWebService::Headers& headers, + unsigned int timeoutInSeconds, + Orthanc::IDynamicObject* payload /* takes ownership */, + NativeStoneApplicationContext& context); + + virtual void Execute(); + }; +} diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Wasm/WasmWebService.cpp --- a/Platforms/Wasm/WasmWebService.cpp Wed Oct 03 17:14:17 2018 +0200 +++ b/Platforms/Wasm/WasmWebService.cpp Fri Oct 05 10:38:16 2018 +0200 @@ -23,6 +23,12 @@ void* payload, unsigned int timeoutInSeconds); + extern void WasmWebService_DeleteAsync(void* callableSuccess, + void* callableFailure, + const char* uri, + const char* headersInJsonString, + void* payload, + unsigned int timeoutInSeconds); void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifyError(void* failureCallable, const char* uri, @@ -116,7 +122,21 @@ body.c_str(), body.size(), payload, timeoutInSeconds); } - void WasmWebService::GetAsync(const std::string& relativeUri, + void WasmWebService::DeleteAsync(const std::string& relativeUri, + const Headers& headers, + Orthanc::IDynamicObject* payload, + MessageHandler* successCallable, + MessageHandler* failureCallable, + unsigned int timeoutInSeconds) + { + std::string uri = baseUri_ + relativeUri; + std::string headersInJsonString; + ToJsonString(headersInJsonString, headers); + WasmWebService_DeleteAsync(successCallable, failureCallable, uri.c_str(), headersInJsonString.c_str(), + payload, timeoutInSeconds); + } + + void WasmWebService::GetAsync(const std::string& relativeUri, const Headers& headers, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Wasm/WasmWebService.h --- a/Platforms/Wasm/WasmWebService.h Wed Oct 03 17:14:17 2018 +0200 +++ b/Platforms/Wasm/WasmWebService.h Fri Oct 05 10:38:16 2018 +0200 @@ -52,6 +52,13 @@ MessageHandler* failureCallable = NULL, unsigned int timeoutInSeconds = 60); + virtual void DeleteAsync(const std::string& uri, + const Headers& headers, + Orthanc::IDynamicObject* payload, + MessageHandler* successCallable, + MessageHandler* failureCallable = NULL, + unsigned int timeoutInSeconds = 60); + virtual void Start() { } diff -r 97f16214dc5e -r aad37d0b6407 Platforms/Wasm/WasmWebService.js --- a/Platforms/Wasm/WasmWebService.js Wed Oct 03 17:14:17 2018 +0200 +++ b/Platforms/Wasm/WasmWebService.js Fri Oct 05 10:38:16 2018 +0200 @@ -57,5 +57,34 @@ } xhr.send(new Uint8ClampedArray(HEAPU8.buffer, body, bodySize)); + }, + + WasmWebService_DeleteAsync: function(callableSuccess, callableFailure, url, headersInJsonString, payload, timeoutInSeconds) { + var xhr = new XMLHttpRequest(); + var url_ = UTF8ToString(url); + var headersInJsonString_ = UTF8ToString(headersInJsonString); + xhr.open('DELETE', url_, true); + xhr.timeout = timeoutInSeconds * 1000; + xhr.responseType = 'arraybuffer'; + xhr.setRequestHeader('Content-type', 'application/octet-stream'); + + var headers = JSON.parse(headersInJsonString_); + for (var key in headers) { + xhr.setRequestHeader(key, headers[key]); + } + + xhr.onreadystatechange = function() { + if (this.readyState == XMLHttpRequest.DONE) { + if (xhr.status === 200) { + WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), + this.response.byteLength, payload); + } else { + WasmWebService_NotifyError(callableFailure, url_, payload); + } + } + } + + xhr.send(); } + }); diff -r 97f16214dc5e -r aad37d0b6407 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed Oct 03 17:14:17 2018 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Fri Oct 05 10:38:16 2018 +0200 @@ -175,6 +175,7 @@ ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceCommandBase.cpp ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceGetCommand.cpp ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServicePostCommand.cpp + ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceDeleteCommand.cpp ${ORTHANC_STONE_ROOT}/Platforms/Generic/Oracle.cpp ${ORTHANC_STONE_ROOT}/Platforms/Generic/OracleWebService.h )