changeset 1068:04a95ee91327 broker

recovery of OrthancStoneSingleFrame
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 15 Oct 2019 19:36:57 +0200
parents 05b2e71ed145
children 5d1b0d2f4b15
files Applications/Generic/NativeStoneApplicationRunner.cpp Applications/Generic/NativeStoneApplicationRunner.h Applications/Samples/SampleMainNative.cpp Applications/Samples/SingleFrameApplication.h Applications/Sdl/SdlStoneApplicationRunner.cpp Applications/Sdl/SdlStoneApplicationRunner.h Applications/StoneApplicationContext.cpp Applications/StoneApplicationContext.h Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h Framework/Deprecated/SmartLoader.cpp Framework/Deprecated/SmartLoader.h Framework/Deprecated/Toolbox/BaseWebService.cpp Framework/Deprecated/Toolbox/OrthancSlicesLoader.cpp Framework/Deprecated/Toolbox/OrthancSlicesLoader.h Framework/Deprecated/Widgets/SliceViewerWidget.cpp Framework/Deprecated/Widgets/SliceViewerWidget.h
diffstat 17 files changed, 179 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Generic/NativeStoneApplicationRunner.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Generic/NativeStoneApplicationRunner.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -36,6 +36,7 @@
 #include <Core/OrthancException.h>
 #include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
+#include <boost/make_shared.hpp>
 #include <boost/program_options.hpp>
 
 namespace OrthancStone
@@ -97,7 +98,7 @@
     DeclareCommandLineOptions(options);
     
     // application specific options
-    application_.DeclareStartupOptions(options);
+    application_->DeclareStartupOptions(options);
 
     boost::program_options::variables_map parameters;
     bool error = false;
@@ -206,23 +207,21 @@
         oracle.Start();
 
         {
-          Deprecated::OracleWebService webService(oracle, webServiceParameters, context);
-          
-          context.SetWebService(webService);
+          context.SetWebService(boost::make_shared<Deprecated::OracleWebService>(oracle, webServiceParameters, context));
           context.SetOrthancBaseUrl(webServiceParameters.GetUrl());
 
           Deprecated::OracleDelayedCallExecutor delayedExecutor(oracle, context);
           context.SetDelayedCallExecutor(delayedExecutor);
 
-          application_.Initialize(&context, statusBar, parameters);
+          application_->Initialize(&context, statusBar, parameters);
 
           {
             NativeStoneApplicationContext::GlobalMutexLocker locker(context);
-            locker.SetCentralWidget(application_.GetCentralWidget());
+            locker.SetCentralWidget(application_->GetCentralWidget());
             locker.GetCentralViewport().SetStatusBar(statusBar);
           }
 
-          std::string title = application_.GetTitle();
+          std::string title = application_->GetTitle();
           if (title.empty())
           {
             title = "Stone of Orthanc";
@@ -243,7 +242,7 @@
       }
 
       LOG(WARNING) << "The application is stopping";
-      application_.Finalize();
+      application_->Finalize();
     }
     catch (Orthanc::OrthancException& e)
     {
--- a/Applications/Generic/NativeStoneApplicationRunner.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Generic/NativeStoneApplicationRunner.h	Tue Oct 15 19:36:57 2019 +0200
@@ -34,10 +34,10 @@
   class NativeStoneApplicationRunner
   {
   protected:
-    IStoneApplication&  application_;
+    boost::shared_ptr<IStoneApplication>  application_;
+    
   public:
-
-    NativeStoneApplicationRunner(IStoneApplication& application)
+    NativeStoneApplicationRunner(boost::shared_ptr<IStoneApplication> application)
       : application_(application)
     {
     }
--- a/Applications/Samples/SampleMainNative.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Samples/SampleMainNative.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -29,12 +29,13 @@
 
 int main(int argc, char* argv[]) 
 {
-  SampleApplication sampleStoneApplication;
+  boost::shared_ptr<SampleApplication> sampleStoneApplication(new SampleApplication);
 
 #if ORTHANC_ENABLE_SDL==1
   OrthancStone::SdlStoneApplicationRunner sdlApplicationRunner(sampleStoneApplication);
   return sdlApplicationRunner.Execute(argc, argv);
 #endif
+  
 #if ORTHANC_ENABLE_QT==1
   OrthancStone::Samples::SampleQtApplicationRunner qtAppRunner(sampleStoneApplication);
   return qtAppRunner.Execute(argc, argv);
--- a/Applications/Samples/SingleFrameApplication.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Samples/SingleFrameApplication.h	Tue Oct 15 19:36:57 2019 +0200
@@ -127,7 +127,7 @@
 
       void OffsetSlice(int offset)
       {
-        if (source_ != NULL)
+        if (source_)
         {
           int slice = static_cast<int>(slice_) + offset;
 
@@ -149,21 +149,15 @@
       }
 
 
-      Deprecated::SliceViewerWidget& GetMainWidget()
-      {
-        return *dynamic_cast<Deprecated::SliceViewerWidget*>(mainWidget_);
-      }
-      
-
       void SetSlice(size_t index)
       {
-        if (source_ != NULL &&
+        if (source_ &&
             index < source_->GetSlicesCount())
         {
           slice_ = static_cast<unsigned int>(index);
           
 #if 1
-          GetMainWidget().SetSlice(source_->GetSlice(slice_).GetGeometry());
+          widget_->SetSlice(source_->GetSlice(slice_).GetGeometry());
 #else
           // TEST for scene extents - Rotate the axes
           double a = 15.0 / 180.0 * boost::math::constants::pi<double>();
@@ -189,21 +183,22 @@
         // Once the geometry of the series is downloaded from Orthanc,
         // display its middle slice, and adapt the viewport to fit this
         // slice
-        if (source_ == &message.GetOrigin())
+        if (source_ &&
+            source_.get() == &message.GetOrigin())
         {
           SetSlice(source_->GetSlicesCount() / 2);
         }
 
-        GetMainWidget().FitContent();
+        widget_->FitContent();
       }
-      
+
+      boost::shared_ptr<Deprecated::SliceViewerWidget>  widget_;
       std::auto_ptr<Interactor>         mainWidgetInteractor_;
-      const Deprecated::DicomSeriesVolumeSlicer*    source_;
+      boost::shared_ptr<Deprecated::DicomSeriesVolumeSlicer> source_;
       unsigned int                      slice_;
 
     public:
       SingleFrameApplication() :
-        source_(NULL),
         slice_(0)
       {
       }
@@ -242,13 +237,15 @@
         std::string instance = parameters["instance"].as<std::string>();
         int frame = parameters["frame"].as<unsigned int>();
 
-        mainWidget_ = new Deprecated::SliceViewerWidget("main-widget");
+        widget_.reset(new Deprecated::SliceViewerWidget("main-widget"));
+        mainWidget_ = widget_.get();  // TODO - awful
 
-        std::auto_ptr<Deprecated::DicomSeriesVolumeSlicer> layer(new Deprecated::DicomSeriesVolumeSlicer(context->GetOrthancApiClient()));
-        source_ = layer.get();
+        boost::shared_ptr<Deprecated::DicomSeriesVolumeSlicer> layer(new Deprecated::DicomSeriesVolumeSlicer);
+        layer->Connect(context->GetOrthancApiClient());
+        source_ = layer;
         layer->LoadFrame(instance, frame);
         Register<Deprecated::IVolumeSlicer::GeometryReadyMessage>(*layer, &SingleFrameApplication::OnMainWidgetGeometryReady);
-        GetMainWidget().AddLayer(layer.release());
+        widget_->AddLayer(layer);
 
         Deprecated::RenderStyle s;
 
@@ -257,11 +254,11 @@
           s.interpolation_ = ImageInterpolation_Bilinear;
         }
 
-        GetMainWidget().SetLayerStyle(0, s);
-        GetMainWidget().SetTransmitMouseOver(true);
+        widget_->SetLayerStyle(0, s);
+        widget_->SetTransmitMouseOver(true);
 
         mainWidgetInteractor_.reset(new Interactor(*this));
-        GetMainWidget().SetInteractor(*mainWidgetInteractor_);
+        widget_->SetInteractor(*mainWidgetInteractor_);
       }
     };
 
--- a/Applications/Sdl/SdlStoneApplicationRunner.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Sdl/SdlStoneApplicationRunner.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -34,6 +34,7 @@
 #include <Core/OrthancException.h>
 #include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
+#include <boost/make_shared.hpp>
 #include <boost/program_options.hpp>
 
 namespace OrthancStone
@@ -103,19 +104,19 @@
     LOG(WARNING) << "Starting the application";
 
     SdlWindow window(title.c_str(), width_, height_, enableOpenGl_);
-    SdlEngine sdl(window, context);
+    boost::shared_ptr<SdlEngine> sdl(boost::make_shared<SdlEngine>(window, context));
 
     {
       NativeStoneApplicationContext::GlobalMutexLocker locker(context);
 
-      sdl.Register<Deprecated::IViewport::ViewportChangedMessage>
+      sdl->Register<Deprecated::IViewport::ViewportChangedMessage>
         (locker.GetCentralViewport(), &SdlEngine::OnViewportChanged);
 
       //context.GetCentralViewport().Register(sdl);  // (*)
     }
 
     context.Start();
-    sdl.Run();
+    sdl->Run();
 
     LOG(WARNING) << "Stopping the application";
 
--- a/Applications/Sdl/SdlStoneApplicationRunner.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/Sdl/SdlStoneApplicationRunner.h	Tue Oct 15 19:36:57 2019 +0200
@@ -39,7 +39,7 @@
     bool          enableOpenGl_;
     
   public:
-    SdlStoneApplicationRunner(IStoneApplication& application) :
+    SdlStoneApplicationRunner(boost::shared_ptr<IStoneApplication> application) :
       NativeStoneApplicationRunner(application)
     {
     }
--- a/Applications/StoneApplicationContext.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/StoneApplicationContext.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -36,31 +36,31 @@
   }
 
 
-  Deprecated::IWebService& StoneApplicationContext::GetWebService()
+  boost::shared_ptr<Deprecated::IWebService> StoneApplicationContext::GetWebService()
   {
     if (webService_ == NULL)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
     
-    return *webService_;
+    return webService_;
   }
 
   
-  Deprecated::OrthancApiClient& StoneApplicationContext::GetOrthancApiClient()
+  boost::shared_ptr<Deprecated::OrthancApiClient> StoneApplicationContext::GetOrthancApiClient()
   {
     if (orthanc_.get() == NULL)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
     
-    return *orthanc_;
+    return orthanc_;
   }
 
   
-  void StoneApplicationContext::SetWebService(Deprecated::IWebService& webService)
+  void StoneApplicationContext::SetWebService(boost::shared_ptr<Deprecated::IWebService> webService)
   {
-    webService_ = &webService;
+    webService_ = webService;
     InitializeOrthanc();
   }
 
--- a/Applications/StoneApplicationContext.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Applications/StoneApplicationContext.h	Tue Oct 15 19:36:57 2019 +0200
@@ -59,16 +59,15 @@
   class StoneApplicationContext : public boost::noncopyable
   {
   private:
-    Deprecated::IWebService*         webService_;
-    Deprecated::IDelayedCallExecutor*            delayedCallExecutor_;
-    std::auto_ptr<Deprecated::OrthancApiClient>  orthanc_;
+    boost::shared_ptr<Deprecated::IWebService>     webService_;
+    Deprecated::IDelayedCallExecutor*  delayedCallExecutor_;   // TODO => shared_ptr ??
+    boost::shared_ptr<Deprecated::OrthancApiClient>  orthanc_;
     std::string                      orthancBaseUrl_;
 
     void InitializeOrthanc();
 
   public:
     StoneApplicationContext() :
-      webService_(NULL),
       delayedCallExecutor_(NULL)
     {
     }
@@ -77,16 +76,11 @@
     {
     }
 
-    bool HasWebService() const
-    {
-      return webService_ != NULL;
-    }
+    boost::shared_ptr<Deprecated::IWebService> GetWebService();
 
-    Deprecated::IWebService& GetWebService();
+    boost::shared_ptr<Deprecated::OrthancApiClient> GetOrthancApiClient();
 
-    Deprecated::OrthancApiClient& GetOrthancApiClient();
-
-    void SetWebService(Deprecated::IWebService& webService);
+    void SetWebService(boost::shared_ptr<Deprecated::IWebService> webService);
 
     void SetOrthancBaseUrl(const std::string& baseUrl);
 
--- a/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -87,46 +87,73 @@
   }
 
 
-  DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer(OrthancApiClient& orthanc) :
-    loader_(orthanc),
+  DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer() :
     quality_(SliceImageQuality_FullPng)
   {
-    // TODO => Move this out of the constructor
-    Register<OrthancSlicesLoader::SliceGeometryReadyMessage>(loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryReady);
-    Register<OrthancSlicesLoader::SliceGeometryErrorMessage>(loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryError);
-    Register<OrthancSlicesLoader::SliceImageReadyMessage>(loader_, &DicomSeriesVolumeSlicer::OnSliceImageReady);
-    Register<OrthancSlicesLoader::SliceImageErrorMessage>(loader_, &DicomSeriesVolumeSlicer::OnSliceImageError);
+  }
+
+  void DicomSeriesVolumeSlicer::Connect(boost::shared_ptr<OrthancApiClient> orthanc)
+  {
+    loader_.reset(new OrthancSlicesLoader(orthanc));
+    Register<OrthancSlicesLoader::SliceGeometryReadyMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryReady);
+    Register<OrthancSlicesLoader::SliceGeometryErrorMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceGeometryError);
+    Register<OrthancSlicesLoader::SliceImageReadyMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceImageReady);
+    Register<OrthancSlicesLoader::SliceImageErrorMessage>(*loader_, &DicomSeriesVolumeSlicer::OnSliceImageError);
   }
 
   
   void DicomSeriesVolumeSlicer::LoadSeries(const std::string& seriesId)
   {
-    loader_.ScheduleLoadSeries(seriesId);
+    if (loader_.get() == NULL)
+    {
+      // Should have called "Connect()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    
+    loader_->ScheduleLoadSeries(seriesId);
   }
 
 
   void DicomSeriesVolumeSlicer::LoadInstance(const std::string& instanceId)
   {
-    loader_.ScheduleLoadInstance(instanceId);
+    if (loader_.get() == NULL)
+    {
+      // Should have called "Connect()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    
+    loader_->ScheduleLoadInstance(instanceId);
   }
 
 
   void DicomSeriesVolumeSlicer::LoadFrame(const std::string& instanceId,
                                           unsigned int frame)
   {
-    loader_.ScheduleLoadFrame(instanceId, frame);
+    if (loader_.get() == NULL)
+    {
+      // Should have called "Connect()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    
+    loader_->ScheduleLoadFrame(instanceId, frame);
   }
 
 
   bool DicomSeriesVolumeSlicer::GetExtent(std::vector<OrthancStone::Vector>& points,
                                           const OrthancStone::CoordinateSystem3D& viewportSlice)
   {
+    if (loader_.get() == NULL)
+    {
+      // Should have called "Connect()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    
     size_t index;
 
-    if (loader_.IsGeometryReady() &&
-        loader_.LookupSlice(index, viewportSlice))
+    if (loader_->IsGeometryReady() &&
+        loader_->LookupSlice(index, viewportSlice))
     {
-      loader_.GetSlice(index).GetExtent(points);
+      loader_->GetSlice(index).GetExtent(points);
       return true;
     }
     else
@@ -138,12 +165,18 @@
   
   void DicomSeriesVolumeSlicer::ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice)
   {
+    if (loader_.get() == NULL)
+    {
+      // Should have called "Connect()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    
     size_t index;
 
-    if (loader_.IsGeometryReady() &&
-        loader_.LookupSlice(index, viewportSlice))
+    if (loader_->IsGeometryReady() &&
+        loader_->LookupSlice(index, viewportSlice))
     {
-      loader_.ScheduleLoadSliceImage(index, quality_);
+      loader_->ScheduleLoadSliceImage(index, quality_);
     }
   }
 }
--- a/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.h	Tue Oct 15 19:36:57 2019 +0200
@@ -80,12 +80,14 @@
   private:
     class RendererFactory;
     
-    OrthancSlicesLoader  loader_;
+    boost::shared_ptr<OrthancSlicesLoader> loader_;
     SliceImageQuality    quality_;
 
   public:
-    DicomSeriesVolumeSlicer(OrthancApiClient& orthanc);
+    DicomSeriesVolumeSlicer();
 
+    void Connect(boost::shared_ptr<OrthancApiClient> orthanc);
+    
     void LoadSeries(const std::string& seriesId);
 
     void LoadInstance(const std::string& instanceId);
@@ -105,12 +107,12 @@
 
     size_t GetSlicesCount() const
     {
-      return loader_.GetSlicesCount();
+      return loader_->GetSlicesCount();
     }
 
     const Slice& GetSlice(size_t slice) const 
     {
-      return loader_.GetSlice(slice);
+      return loader_->GetSlice(slice);
     }
 
     virtual bool GetExtent(std::vector<OrthancStone::Vector>& points,
--- a/Framework/Deprecated/SmartLoader.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/SmartLoader.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -113,7 +113,7 @@
   };
 
 
-  SmartLoader::SmartLoader(OrthancApiClient& orthancApiClient) :
+  SmartLoader::SmartLoader(boost::shared_ptr<OrthancApiClient> orthancApiClient) :
     imageQuality_(SliceImageQuality_FullPam),
     orthancApiClient_(orthancApiClient)
   {
@@ -131,7 +131,7 @@
     //   the messages to its observables
     // in both cases, we must be carefull about objects lifecycle !!!
 
-    std::auto_ptr<IVolumeSlicer> layerSource;
+    boost::shared_ptr<IVolumeSlicer> layerSource;
     std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame);
     SmartLoader::CachedSlice* cachedSlice = NULL;
 
@@ -142,7 +142,8 @@
     }
     else
     {
-      layerSource.reset(new DicomSeriesVolumeSlicer(orthancApiClient_));
+      layerSource.reset(new DicomSeriesVolumeSlicer);
+      dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->Connect(orthancApiClient_);
       dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_);
       Register<IVolumeSlicer::GeometryReadyMessage>(*layerSource, &SmartLoader::OnLayerGeometryReady);
       Register<DicomSeriesVolumeSlicer::FrameReadyMessage>(*layerSource, &SmartLoader::OnFrameReady);
@@ -153,11 +154,11 @@
     // make sure that the widget registers the events before we trigger them
     if (sliceViewer.GetLayerCount() == layerIndex)
     {
-      sliceViewer.AddLayer(layerSource.release());
+      sliceViewer.AddLayer(layerSource);
     }
     else if (sliceViewer.GetLayerCount() > layerIndex)
     {
-      sliceViewer.ReplaceLayer(layerIndex, layerSource.release());
+      sliceViewer.ReplaceLayer(layerIndex, layerSource);
     }
     else
     {
@@ -190,8 +191,8 @@
 
     cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice);
 
-    std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer(orthancApiClient_));
-
+    std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer);
+    dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->Connect(orthancApiClient_);
     dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_);
     Register<IVolumeSlicer::GeometryReadyMessage>(*layerSource, &SmartLoader::OnLayerGeometryReady);
     Register<DicomSeriesVolumeSlicer::FrameReadyMessage>(*layerSource, &SmartLoader::OnFrameReady);
--- a/Framework/Deprecated/SmartLoader.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/SmartLoader.h	Tue Oct 15 19:36:57 2019 +0200
@@ -42,10 +42,10 @@
     PreloadingInstances preloadingInstances_;
 
     SliceImageQuality     imageQuality_;
-    OrthancApiClient&     orthancApiClient_;
+    boost::shared_ptr<OrthancApiClient>  orthancApiClient_;
 
   public:
-    SmartLoader(OrthancApiClient& orthancApiClient);  // TODO: add maxPreloadStorageSizeInBytes
+    SmartLoader(boost::shared_ptr<OrthancApiClient> orthancApiClient);  // TODO: add maxPreloadStorageSizeInBytes
 
 //    void PreloadStudy(const std::string studyId);
 //    void PreloadSeries(const std::string seriesId);
--- a/Framework/Deprecated/Toolbox/BaseWebService.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Toolbox/BaseWebService.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -97,9 +97,9 @@
       GetAsyncInternal(uri, headers,
                        new BaseWebService::BaseWebServicePayload(successCallback, failureCallback, payload), // ownership is transfered
                        new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestSuccessMessage>
-                       (shared_from_this(), &BaseWebService::CacheAndNotifyHttpSuccess),
+                       (GetSharedObserver(), &BaseWebService::CacheAndNotifyHttpSuccess),
                        new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestErrorMessage>
-                       (shared_from_this(), &BaseWebService::NotifyHttpError),
+                       (GetSharedObserver(), &BaseWebService::NotifyHttpError),
                        timeoutInSeconds);
     }
     else
--- a/Framework/Deprecated/Toolbox/OrthancSlicesLoader.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Toolbox/OrthancSlicesLoader.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -639,7 +639,7 @@
   }
   
   
-  OrthancSlicesLoader::OrthancSlicesLoader(OrthancApiClient& orthanc) :
+  OrthancSlicesLoader::OrthancSlicesLoader(boost::shared_ptr<OrthancApiClient> orthanc) :
     orthanc_(orthanc),
     state_(State_Initialization)
   {
@@ -655,10 +655,10 @@
     else
     {
       state_ = State_LoadingGeometry;
-      orthanc_.GetJsonAsync("/series/" + seriesId + "/instances-tags",
-                            new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseSeriesGeometry),
-                            new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
-                            NULL);
+      orthanc_->GetJsonAsync("/series/" + seriesId + "/instances-tags",
+                             new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseSeriesGeometry),
+                             new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
+                             NULL);
     }
   }
   
@@ -674,10 +674,10 @@
       
       // Tag "3004-000c" is "Grid Frame Offset Vector", which is
       // mandatory to read RT DOSE, but is too long to be returned by default
-      orthanc_.GetJsonAsync("/instances/" + instanceId + "/tags?ignore-length=3004-000c",
-                            new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseInstanceGeometry),
-                            new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
-                            Operation::DownloadInstanceGeometry(instanceId));
+      orthanc_->GetJsonAsync("/instances/" + instanceId + "/tags?ignore-length=3004-000c",
+                             new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseInstanceGeometry),
+                             new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
+                             Operation::DownloadInstanceGeometry(instanceId));
     }
   }
   
@@ -693,10 +693,10 @@
     {
       state_ = State_LoadingGeometry;
 
-      orthanc_.GetJsonAsync("/instances/" + instanceId + "/tags",
-                            new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseFrameGeometry),
-                            new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
-                            Operation::DownloadFrameGeometry(instanceId, frame));
+      orthanc_->GetJsonAsync("/instances/" + instanceId + "/tags",
+                             new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(GetSharedObserver(), &OrthancSlicesLoader::ParseFrameGeometry),
+                             new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(GetSharedObserver(), &OrthancSlicesLoader::OnGeometryError),
+                             Operation::DownloadFrameGeometry(instanceId, frame));
     }
   }
   
@@ -767,15 +767,15 @@
         throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
     
-    orthanc_.GetBinaryAsync(uri, "image/png",
-                            new OrthancStone::Callable<OrthancSlicesLoader, 
-                            OrthancApiClient::BinaryResponseReadyMessage>
-                            (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePng),
-                            new OrthancStone::Callable<OrthancSlicesLoader, 
-                            IWebService::HttpRequestErrorMessage>
-                            (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
-                            Operation::DownloadSliceImage(
-                              static_cast<unsigned int>(index), slice, SliceImageQuality_FullPng));
+    orthanc_->GetBinaryAsync(uri, "image/png",
+                             new OrthancStone::Callable<OrthancSlicesLoader, 
+                             OrthancApiClient::BinaryResponseReadyMessage>
+                             (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePng),
+                             new OrthancStone::Callable<OrthancSlicesLoader, 
+                             IWebService::HttpRequestErrorMessage>
+                             (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
+                             Operation::DownloadSliceImage(
+                               static_cast<unsigned int>(index), slice, SliceImageQuality_FullPng));
   }
   
   void OrthancSlicesLoader::ScheduleSliceImagePam(const Slice& slice,
@@ -803,15 +803,15 @@
         throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
-    orthanc_.GetBinaryAsync(uri, "image/x-portable-arbitrarymap",
-                            new OrthancStone::Callable<OrthancSlicesLoader, 
-                            OrthancApiClient::BinaryResponseReadyMessage>
-                            (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePam),
-                            new OrthancStone::Callable<OrthancSlicesLoader, 
-                            IWebService::HttpRequestErrorMessage>
-                            (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
-                            Operation::DownloadSliceImage(static_cast<unsigned int>(index), 
-                                                          slice, SliceImageQuality_FullPam));
+    orthanc_->GetBinaryAsync(uri, "image/x-portable-arbitrarymap",
+                             new OrthancStone::Callable<OrthancSlicesLoader, 
+                             OrthancApiClient::BinaryResponseReadyMessage>
+                             (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImagePam),
+                             new OrthancStone::Callable<OrthancSlicesLoader, 
+                             IWebService::HttpRequestErrorMessage>
+                             (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
+                             Operation::DownloadSliceImage(static_cast<unsigned int>(index), 
+                                                           slice, SliceImageQuality_FullPam));
   }
 
 
@@ -846,15 +846,15 @@
                        "-" + slice.GetOrthancInstanceId() + "_" +
                        boost::lexical_cast<std::string>(slice.GetFrame()));
 
-    orthanc_.GetJsonAsync(uri,
-                          new OrthancStone::Callable<OrthancSlicesLoader, 
-                          OrthancApiClient::JsonResponseReadyMessage>
-                          (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImageJpeg),
-                          new OrthancStone::Callable<OrthancSlicesLoader, 
-                          IWebService::HttpRequestErrorMessage>
-                          (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
-                          Operation::DownloadSliceImage(
-                            static_cast<unsigned int>(index), slice, quality));
+    orthanc_->GetJsonAsync(uri,
+                           new OrthancStone::Callable<OrthancSlicesLoader, 
+                           OrthancApiClient::JsonResponseReadyMessage>
+                           (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceImageJpeg),
+                           new OrthancStone::Callable<OrthancSlicesLoader, 
+                           IWebService::HttpRequestErrorMessage>
+                           (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
+                           Operation::DownloadSliceImage(
+                             static_cast<unsigned int>(index), slice, quality));
   }
   
   
@@ -887,15 +887,15 @@
     {
       std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" +
                          boost::lexical_cast<std::string>(slice.GetFrame()) + "/raw.gz");
-      orthanc_.GetBinaryAsync(uri, IWebService::HttpHeaders(),
-                              new OrthancStone::Callable<OrthancSlicesLoader, 
-                              OrthancApiClient::BinaryResponseReadyMessage>
-                              (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceRawImage),
-                              new OrthancStone::Callable<OrthancSlicesLoader,
-                              IWebService::HttpRequestErrorMessage>
-                              (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
-                              Operation::DownloadSliceRawImage(
-                                static_cast<unsigned int>(index), slice));
+      orthanc_->GetBinaryAsync(uri, IWebService::HttpHeaders(),
+                               new OrthancStone::Callable<OrthancSlicesLoader, 
+                               OrthancApiClient::BinaryResponseReadyMessage>
+                               (GetSharedObserver(), &OrthancSlicesLoader::ParseSliceRawImage),
+                               new OrthancStone::Callable<OrthancSlicesLoader,
+                               IWebService::HttpRequestErrorMessage>
+                               (GetSharedObserver(), &OrthancSlicesLoader::OnSliceImageError),
+                               Operation::DownloadSliceRawImage(
+                                 static_cast<unsigned int>(index), slice));
     }
   }
 }
--- a/Framework/Deprecated/Toolbox/OrthancSlicesLoader.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Toolbox/OrthancSlicesLoader.h	Tue Oct 15 19:36:57 2019 +0200
@@ -146,7 +146,7 @@
 
     class Operation;
 
-    OrthancApiClient&  orthanc_;
+    boost::shared_ptr<OrthancApiClient>  orthanc_;
     State         state_;
     OrthancStone::SlicesSorter  slices_;
 
@@ -187,7 +187,7 @@
     
   public:
     OrthancSlicesLoader(//ISliceLoaderObserver& callback,
-                        OrthancApiClient& orthancApi);
+      boost::shared_ptr<OrthancApiClient> orthancApi);
 
     void ScheduleLoadSeries(const std::string& seriesId);
 
--- a/Framework/Deprecated/Widgets/SliceViewerWidget.cpp	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Widgets/SliceViewerWidget.cpp	Tue Oct 15 19:36:57 2019 +0200
@@ -250,7 +250,7 @@
     {
       index = found->second;
       assert(index < layers_.size() &&
-             layers_[index] == &layer);
+             layers_[index].get() == &layer);
       return true;
     }
   }
@@ -372,14 +372,6 @@
   }
   
   
-  SliceViewerWidget::~SliceViewerWidget()
-  {
-    for (size_t i = 0; i < layers_.size(); i++)
-    {
-      delete layers_[i];
-    }
-  }
-  
   void SliceViewerWidget::ObserveLayer(IVolumeSlicer& layer)
   {
     // currently ignoring errors of type IVolumeSlicer::GeometryErrorMessage
@@ -392,7 +384,7 @@
   }
 
 
-  size_t SliceViewerWidget::AddLayer(IVolumeSlicer* layer)  // Takes ownership
+  size_t SliceViewerWidget::AddLayer(boost::shared_ptr<IVolumeSlicer> layer)
   {
     if (layer == NULL)
     {
@@ -402,7 +394,7 @@
     size_t index = layers_.size();
     layers_.push_back(layer);
     styles_.push_back(RenderStyle());
-    layersIndex_[layer] = index;
+    layersIndex_[layer.get()] = index;
 
     ResetPendingScene();
 
@@ -414,7 +406,8 @@
   }
 
 
-  void SliceViewerWidget::ReplaceLayer(size_t index, IVolumeSlicer* layer)  // Takes ownership
+  void SliceViewerWidget::ReplaceLayer(size_t index,
+                                       boost::shared_ptr<IVolumeSlicer> layer)
   {
     if (layer == NULL)
     {
@@ -426,9 +419,8 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
-    delete layers_[index];
     layers_[index] = layer;
-    layersIndex_[layer] = index;
+    layersIndex_[layer.get()] = index;
 
     ResetPendingScene();
 
@@ -445,13 +437,13 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
-    IVolumeSlicer* previousLayer = layers_[index];
+    IVolumeSlicer* previousLayer = layers_[index].get();
     layersIndex_.erase(layersIndex_.find(previousLayer));
     layers_.erase(layers_.begin() + index);
     changedLayers_.erase(changedLayers_.begin() + index);
     styles_.erase(styles_.begin() + index);
 
-    delete layers_[index];
+    layers_[index].reset();
 
     currentScene_->DeleteLayer(index);
     ResetPendingScene();
--- a/Framework/Deprecated/Widgets/SliceViewerWidget.h	Tue Oct 15 18:11:40 2019 +0200
+++ b/Framework/Deprecated/Widgets/SliceViewerWidget.h	Tue Oct 15 19:36:57 2019 +0200
@@ -72,7 +72,7 @@
 
     bool                         started_;
     LayersIndex                  layersIndex_;
-    std::vector<IVolumeSlicer*>  layers_;
+    std::vector<boost::shared_ptr<IVolumeSlicer> >  layers_;
     std::vector<RenderStyle>     styles_;
     OrthancStone::CoordinateSystem3D           plane_;
     std::auto_ptr<Scene>         currentScene_;
@@ -119,11 +119,13 @@
     void InvalidateLayer(size_t layer);
     
   public:
-    virtual ~SliceViewerWidget();
+    virtual ~SliceViewerWidget()
+    {
+    }
 
-    size_t AddLayer(IVolumeSlicer* layer);  // Takes ownership
+    size_t AddLayer(boost::shared_ptr<IVolumeSlicer> layer);
 
-    void ReplaceLayer(size_t layerIndex, IVolumeSlicer* layer); // Takes ownership
+    void ReplaceLayer(size_t layerIndex, boost::shared_ptr<IVolumeSlicer> layer); // Takes ownership
 
     void RemoveLayer(size_t layerIndex);