changeset 1473:9cbc6d21ae89

SeriesThumbnailsLoader::SuccessMessage::DecodeImage(), fix static builds
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 15 Jun 2020 18:02:49 +0200
parents 474360793956
children d1dde1f86d4a
files Framework/Loaders/DicomSource.h Framework/Loaders/SeriesThumbnailsLoader.cpp Framework/Loaders/SeriesThumbnailsLoader.h Resources/CMake/BoostExtendedConfiguration.cmake Resources/CMake/OrthancStoneConfiguration.cmake Resources/CMake/Utilities.cmake Samples/Sdl/BoostExtendedConfiguration.cmake Samples/Sdl/CMakeLists.txt Samples/Sdl/RtViewer/CMakeLists.txt Samples/Sdl/Utilities.cmake
diffstat 10 files changed, 192 insertions(+), 149 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Loaders/DicomSource.h	Mon Jun 15 16:26:57 2020 +0200
+++ b/Framework/Loaders/DicomSource.h	Mon Jun 15 18:02:49 2020 +0200
@@ -98,6 +98,13 @@
                                           const std::map<std::string, std::string>& headers,
                                           Orthanc::IDynamicObject* payload /* takes ownership */) const;
     
+    IOracleCommand* CreateDicomWebCommand(const std::string& uri,
+                                          Orthanc::IDynamicObject* payload /* takes ownership */) const
+    {
+      std::map<std::string, std::string> none;
+      return CreateDicomWebCommand(uri, none, none, payload);
+    }
+    
     void AutodetectOrthancFeatures(const std::string& system,
                                    const std::string& plugins);
 
--- a/Framework/Loaders/SeriesThumbnailsLoader.cpp	Mon Jun 15 16:26:57 2020 +0200
+++ b/Framework/Loaders/SeriesThumbnailsLoader.cpp	Mon Jun 15 18:02:49 2020 +0200
@@ -24,6 +24,7 @@
 #include <DicomFormat/DicomMap.h>
 #include <DicomFormat/DicomInstanceHasher.h>
 #include <Images/ImageProcessing.h>
+#include <Images/JpegReader.h>
 #include <Images/JpegWriter.h>
 #include <OrthancException.h>
 
@@ -71,6 +72,37 @@
   }
 
 
+  Orthanc::ImageAccessor* SeriesThumbnailsLoader::SuccessMessage::DecodeImage() const
+  {
+    if (GetType() != SeriesThumbnailType_Image)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+    Orthanc::MimeType mime;
+    if (!Orthanc::LookupMimeType(mime, GetMime()))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented,
+                                      "Unsupported MIME type for thumbnail: " + GetMime());
+    }
+
+    switch (mime)
+    {
+      case Orthanc::MimeType_Jpeg:
+      {
+        std::unique_ptr<Orthanc::JpegReader> reader(new Orthanc::JpegReader);
+        reader->ReadFromMemory(GetEncodedImage());
+        return reader.release();
+      }
+
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented,
+                                        "Cannot decode MIME type for thumbnail: " + GetMime());
+    }
+  }
+
+
+
   void SeriesThumbnailsLoader::AcquireThumbnail(const DicomSource& source,
                                                 const std::string& studyInstanceUid,
                                                 const std::string& seriesInstanceUid,
@@ -92,7 +124,7 @@
       found->second = protection.release();
     }
 
-    ThumbnailLoadedMessage message(*this, source, studyInstanceUid, seriesInstanceUid, *thumbnail);
+    SuccessMessage message(*this, source, studyInstanceUid, seriesInstanceUid, *thumbnail);
     BroadcastMessage(message);
   }
 
@@ -247,16 +279,12 @@
     virtual void HandleError()
     {
       // The DICOMweb wasn't able to generate a thumbnail, try to
-      // retrieve the SopClassUID tag using QIDO-RS
-
-      std::map<std::string, std::string> arguments, headers;
-      arguments["0020000D"] = GetStudyInstanceUid();
-      arguments["0020000E"] = GetSeriesInstanceUid();
-      arguments["includefield"] = "00080016";
+      // retrieve the SopClassUID tag using a call to "/metadata"
 
       std::unique_ptr<IOracleCommand> command(
         GetSource().CreateDicomWebCommand(
-          "/instances", arguments, headers, new DicomWebSopClassHandler(
+          "/studies/" + GetStudyInstanceUid() + "/series/" + GetSeriesInstanceUid() + "/metadata",
+          new DicomWebSopClassHandler(
             GetLoader(), GetSource(), GetStudyInstanceUid(), GetSeriesInstanceUid())));
       GetLoader()->Schedule(command.release());
     }
@@ -455,9 +483,10 @@
   }
     
   
-  boost::shared_ptr<IObserver> SeriesThumbnailsLoader::Factory::Create(ILoadersContext::ILock& stone)
+  boost::shared_ptr<SeriesThumbnailsLoader> SeriesThumbnailsLoader::Create(ILoadersContext::ILock& stone,
+                                                                           int priority)
   {
-    boost::shared_ptr<SeriesThumbnailsLoader> result(new SeriesThumbnailsLoader(stone.GetContext(), priority_));
+    boost::shared_ptr<SeriesThumbnailsLoader> result(new SeriesThumbnailsLoader(stone.GetContext(), priority));
     result->Register<GetOrthancImageCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle);
     result->Register<HttpCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle);
     result->Register<OracleCommandExceptionMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle);
--- a/Framework/Loaders/SeriesThumbnailsLoader.h	Mon Jun 15 16:26:57 2020 +0200
+++ b/Framework/Loaders/SeriesThumbnailsLoader.h	Mon Jun 15 18:02:49 2020 +0200
@@ -77,7 +77,7 @@
     };
 
   public:
-    class ThumbnailLoadedMessage : public OriginMessage<SeriesThumbnailsLoader>
+    class SuccessMessage : public OriginMessage<SeriesThumbnailsLoader>
     {
       ORTHANC_STONE_MESSAGE(__FILE__, __LINE__);
       
@@ -88,11 +88,11 @@
       const Thumbnail&     thumbnail_;
 
     public:
-      ThumbnailLoadedMessage(const SeriesThumbnailsLoader& origin,
-                             const DicomSource& source,
-                             const std::string& studyInstanceUid,
-                             const std::string& seriesInstanceUid,
-                             const Thumbnail& thumbnail) :
+      SuccessMessage(const SeriesThumbnailsLoader& origin,
+                     const DicomSource& source,
+                     const std::string& studyInstanceUid,
+                     const std::string& seriesInstanceUid,
+                     const Thumbnail& thumbnail) :
         OriginMessage(origin),
         source_(source),
         studyInstanceUid_(studyInstanceUid),
@@ -130,6 +130,8 @@
       {
         return thumbnail_.GetMime();
       }
+
+      Orthanc::ImageAccessor* DecodeImage() const;
     };
 
   private:
@@ -184,7 +186,10 @@
         priority_ = priority;
       }
 
-      virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context);
+      virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context)
+      {
+        return SeriesThumbnailsLoader::Create(context, priority_);
+      }
     };
 
 
@@ -193,6 +198,10 @@
       Clear();
     }
 
+
+    static boost::shared_ptr<SeriesThumbnailsLoader> Create(ILoadersContext::ILock& context,
+                                                            int priority);
+
     void SetThumbnailSize(unsigned int width,
                           unsigned int height);
     
--- a/Resources/CMake/BoostExtendedConfiguration.cmake	Mon Jun 15 16:26:57 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-# Stone of Orthanc
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, Belgium
-# Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>.
-
-
-if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST)
-  list(APPEND BOOST_EXTENDED_SOURCES
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/cmdline.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/config_file.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/convert.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/options_description.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/parsers.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/positional_options.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/split.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/utf8_codecvt_facet.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/value_semantic.cpp
-    ${BOOST_SOURCES_DIR}/libs/program_options/src/variables_map.cpp
-    ${BOOST_SOURCES_DIR}/libs/chrono/src/thread_clock.cpp
-    ${BOOST_SOURCES_DIR}/libs/chrono/src/chrono.cpp
-    ${BOOST_SOURCES_DIR}/libs/chrono/src/process_cpu_clocks.cpp
-    #${BOOST_SOURCES_DIR}/libs/program_options/src/winmain.cpp
-    )
-  add_definitions(-DBOOST_PROGRAM_OPTIONS_NO_LIB)
-else()
-  list(APPEND ORTHANC_BOOST_COMPONENTS program_options)
-endif()
-
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Mon Jun 15 16:26:57 2020 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Mon Jun 15 18:02:49 2020 +0200
@@ -92,7 +92,6 @@
 SET(ORTHANC_STONE_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..)
 
 include(FindPkgConfig)
-include(${CMAKE_CURRENT_LIST_DIR}/BoostExtendedConfiguration.cmake)
 include(${CMAKE_CURRENT_LIST_DIR}/CairoConfiguration.cmake)
 include(${CMAKE_CURRENT_LIST_DIR}/FreetypeConfiguration.cmake)
 include(${CMAKE_CURRENT_LIST_DIR}/PixmanConfiguration.cmake)
@@ -521,7 +520,6 @@
   # Optional components
   ${SDL_SOURCES}
   ${QT_SOURCES}
-  ${BOOST_EXTENDED_SOURCES}
   ${GLEW_SOURCES}
   )
 
--- a/Resources/CMake/Utilities.cmake	Mon Jun 15 16:26:57 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-
-
-macro(GetFilenameFromPath TargetVariable Path)
-#message(STATUS "GetFilenameFromPath (1): Path = ${Path} TargetVariable = ${${TargetVariable}}")
-string(REPLACE "\\" "/" PathWithFwdSlashes "${Path}")
-string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${PathWithFwdSlashes}")
-#message(STATUS "GetFilenameFromPath (2): Path = ${Path} Path = ${PathWithFwdSlashes} TargetVariable = ${TargetVariable}")
-endmacro()
-
-macro(GetFilePathWithoutLastExtension TargetVariable FilePath)
-string(REGEX REPLACE "(^.*)\\.([^\\.]+)" "\\1" ${TargetVariable} "${FilePath}")
-#message(STATUS "GetFileNameWithoutLastExtension: FilePath = ${FilePath} TargetVariable = ${${TargetVariable}}")
-endmacro()
-
-macro(Test_GetFilePathWithoutLastExtension)
-set(tmp "/prout/zi/goui.goui.cpp")
-GetFilePathWithoutLastExtension(TargetVariable "${tmp}")
-if(NOT ("${TargetVariable}" STREQUAL "/prout/zi/goui.goui"))
-  message(FATAL_ERROR "Test_GetFilePathWithoutLastExtension failed (1)")
-else()
-  #message(STATUS "Test_GetFilePathWithoutLastExtension: <<OK>>")
-endif()
-endmacro()
-
-Test_GetFilePathWithoutLastExtension()
-
-macro(Test_GetFilenameFromPath)
-set(tmp "/prout/../../dada/zi/goui.goui.cpp")
-GetFilenameFromPath(TargetVariable "${tmp}")
-if(NOT ("${TargetVariable}" STREQUAL "goui.goui.cpp"))
-  message(FATAL_ERROR "Test_GetFilenameFromPath failed")
-else()
-  #message(STATUS "Test_GetFilenameFromPath: <<OK>>")
-endif()
-endmacro()
-
-Test_GetFilenameFromPath()
-
-macro(SortFilesInSourceGroups)
-  if(FALSE)
-    foreach(source IN LISTS ORTHANC_STONE_SOURCES)
-        # if("${source}" MATCHES ".*/pixman.*\\.c")
-        #   message("pixman source: ${source}")
-        # elseif("${source}" MATCHES ".*/pixman.*\\.c")
-        #   message("pixman header: ${source}")
-        # endif()
-        
-        if("${source}" MATCHES ".*\\.\\./.*")
-          message("source raw: ${source}")
-          #file(TO_CMAKE_PATH ${source} sourceCMakePath)
-          get_filename_component(sourceCMakePath ${source} ABSOLUTE)
-          message("source CMake: ${sourceCMakePath}")
-        endif()
-
-        # returns the containing directory with forward slashes
-        # get_filename_component(source_path "${source}" PATH) 
-
-        # converts / to \
-        # string(REPLACE "/" "\\" source_path_msvc "${source_path}")
-        #source_group("Stone ${source_path_msvc}" FILES "${source}")
-    endforeach()
-  endif()
-
-  source_group("Orthanc Framework\\Sources" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*cpp")
-  source_group("Orthanc Framework\\Headers" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*hpp")
-  source_group("Orthanc Framework\\Headers" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*h")
-
-  source_group("Stone Library\\Sources" REGULAR_EXPRESSION ".*/orthanc-stone/.*cpp")
-  source_group("Stone Library\\Headers" REGULAR_EXPRESSION ".*/orthanc-stone/.*hpp")
-  source_group("Stone Library\\Headers" REGULAR_EXPRESSION ".*/orthanc-stone/.*h")
-
-  source_group("Stone Samples\\Source" REGULAR_EXPRESSION ".*orthanc-stone/Samples/.*\\.cpp")
-  source_group("Stone Samples\\Headers" REGULAR_EXPRESSION ".*orthanc-stone/Samples/.*\\.h")
-
-  source_group("ThirdParty\\cairo" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/cairo[^/]*/.*")
-  source_group("ThirdParty\\pixman" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/pixman[^/]*/.*")
-  source_group("ThirdParty\\base64" REGULAR_EXPRESSION ".*ThirdParty/base64.*")
-  source_group("ThirdParty\\SDL2" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/SDL2.*")
-  source_group("ThirdParty\\glew" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/glew.*")
-  source_group("AUTOGENERATED" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/AUTOGENERATED/.*")
-  source_group("ThirdParty\\minizip" REGULAR_EXPRESSION ".*ThirdParty/minizip/.*")
-  source_group("ThirdParty\\md5" REGULAR_EXPRESSION ".*ThirdParty/md5/.*")
-endmacro()
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Samples/Sdl/BoostExtendedConfiguration.cmake	Mon Jun 15 18:02:49 2020 +0200
@@ -0,0 +1,40 @@
+# Stone of Orthanc
+# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+# Department, University Hospital of Liege, Belgium
+# Copyright (C) 2017-2020 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 <http://www.gnu.org/licenses/>.
+
+
+if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST)
+  set(BOOST_EXTENDED_SOURCES
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/cmdline.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/config_file.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/convert.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/options_description.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/parsers.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/positional_options.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/split.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/utf8_codecvt_facet.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/value_semantic.cpp
+    ${BOOST_SOURCES_DIR}/libs/program_options/src/variables_map.cpp
+    ${BOOST_SOURCES_DIR}/libs/chrono/src/thread_clock.cpp
+    ${BOOST_SOURCES_DIR}/libs/chrono/src/chrono.cpp
+    ${BOOST_SOURCES_DIR}/libs/chrono/src/process_cpu_clocks.cpp
+    #${BOOST_SOURCES_DIR}/libs/program_options/src/winmain.cpp
+    )
+  add_definitions(-DBOOST_PROGRAM_OPTIONS_NO_LIB)
+else()
+  link_libraries(boost_program_options)
+endif()
--- a/Samples/Sdl/CMakeLists.txt	Mon Jun 15 16:26:57 2020 +0200
+++ b/Samples/Sdl/CMakeLists.txt	Mon Jun 15 18:02:49 2020 +0200
@@ -23,9 +23,9 @@
 set(ENABLE_WEB_CLIENT ON)
 set(ORTHANC_SANDBOXED OFF)
 
-include(${STONE_ROOT}/Resources/CMake/BoostExtendedConfiguration.cmake)
 include(${STONE_ROOT}/Resources/CMake/OrthancStoneConfiguration.cmake)
-include(${STONE_ROOT}/Resources/CMake/Utilities.cmake)
+include(${CMAKE_SOURCE_DIR}/BoostExtendedConfiguration.cmake)
+include(${CMAKE_SOURCE_DIR}/Utilities.cmake)
 
 
 
@@ -51,6 +51,7 @@
 add_library(OrthancStone STATIC
   ${ORTHANC_STONE_SOURCES}
   ${AUTOGENERATED_SOURCES}
+  ${BOOST_EXTENDED_SOURCES}
   )
 
 message(${AUTOGENERATED_SOURCES})
@@ -80,7 +81,6 @@
   ../Common/SampleHelpers.h
   SingleFrameViewer/SdlSimpleViewerApplication.h
   SingleFrameViewer/SdlSimpleViewer.cpp
-  ${BOOST_EXTENDED_SOURCES}
   )
 
 target_link_libraries(SdlSimpleViewer OrthancStone ${DCMTK_LIBRARIES})
--- a/Samples/Sdl/RtViewer/CMakeLists.txt	Mon Jun 15 16:26:57 2020 +0200
+++ b/Samples/Sdl/RtViewer/CMakeLists.txt	Mon Jun 15 18:02:49 2020 +0200
@@ -18,9 +18,9 @@
 SET(ENABLE_WEB_CLIENT ON)
 SET(ORTHANC_SANDBOXED OFF)
 
-include(${STONE_ROOT}/Resources/CMake/BoostExtendedConfiguration.cmake)
 include(${STONE_ROOT}/Resources/CMake/OrthancStoneConfiguration.cmake)
-include(${STONE_ROOT}/Resources/CMake/Utilities.cmake)
+include(${CMAKE_SOURCE_DIR}/../BoostExtendedConfiguration.cmake)
+include(${CMAKE_SOURCE_DIR}/../Utilities.cmake)
 
 DownloadPackage(
   "a24b8136b8f3bb93f166baf97d9328de"
@@ -51,6 +51,7 @@
   ../../Common/SampleHelpers.h
   ${ORTHANC_STONE_SOURCES}
   ${AUTOGENERATED_SOURCES}
+  ${BOOST_EXTENDED_SOURCES}
   )
 
 target_link_libraries(RtViewerSdl ${DCMTK_LIBRARIES})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Samples/Sdl/Utilities.cmake	Mon Jun 15 18:02:49 2020 +0200
@@ -0,0 +1,84 @@
+
+
+macro(GetFilenameFromPath TargetVariable Path)
+#message(STATUS "GetFilenameFromPath (1): Path = ${Path} TargetVariable = ${${TargetVariable}}")
+string(REPLACE "\\" "/" PathWithFwdSlashes "${Path}")
+string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${PathWithFwdSlashes}")
+#message(STATUS "GetFilenameFromPath (2): Path = ${Path} Path = ${PathWithFwdSlashes} TargetVariable = ${TargetVariable}")
+endmacro()
+
+macro(GetFilePathWithoutLastExtension TargetVariable FilePath)
+string(REGEX REPLACE "(^.*)\\.([^\\.]+)" "\\1" ${TargetVariable} "${FilePath}")
+#message(STATUS "GetFileNameWithoutLastExtension: FilePath = ${FilePath} TargetVariable = ${${TargetVariable}}")
+endmacro()
+
+macro(Test_GetFilePathWithoutLastExtension)
+set(tmp "/prout/zi/goui.goui.cpp")
+GetFilePathWithoutLastExtension(TargetVariable "${tmp}")
+if(NOT ("${TargetVariable}" STREQUAL "/prout/zi/goui.goui"))
+  message(FATAL_ERROR "Test_GetFilePathWithoutLastExtension failed (1)")
+else()
+  #message(STATUS "Test_GetFilePathWithoutLastExtension: <<OK>>")
+endif()
+endmacro()
+
+Test_GetFilePathWithoutLastExtension()
+
+macro(Test_GetFilenameFromPath)
+set(tmp "/prout/../../dada/zi/goui.goui.cpp")
+GetFilenameFromPath(TargetVariable "${tmp}")
+if(NOT ("${TargetVariable}" STREQUAL "goui.goui.cpp"))
+  message(FATAL_ERROR "Test_GetFilenameFromPath failed")
+else()
+  #message(STATUS "Test_GetFilenameFromPath: <<OK>>")
+endif()
+endmacro()
+
+Test_GetFilenameFromPath()
+
+macro(SortFilesInSourceGroups)
+  if(FALSE)
+    foreach(source IN LISTS ORTHANC_STONE_SOURCES)
+        # if("${source}" MATCHES ".*/pixman.*\\.c")
+        #   message("pixman source: ${source}")
+        # elseif("${source}" MATCHES ".*/pixman.*\\.c")
+        #   message("pixman header: ${source}")
+        # endif()
+        
+        if("${source}" MATCHES ".*\\.\\./.*")
+          message("source raw: ${source}")
+          #file(TO_CMAKE_PATH ${source} sourceCMakePath)
+          get_filename_component(sourceCMakePath ${source} ABSOLUTE)
+          message("source CMake: ${sourceCMakePath}")
+        endif()
+
+        # returns the containing directory with forward slashes
+        # get_filename_component(source_path "${source}" PATH) 
+
+        # converts / to \
+        # string(REPLACE "/" "\\" source_path_msvc "${source_path}")
+        #source_group("Stone ${source_path_msvc}" FILES "${source}")
+    endforeach()
+  endif()
+
+  source_group("Orthanc Framework\\Sources" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*cpp")
+  source_group("Orthanc Framework\\Headers" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*hpp")
+  source_group("Orthanc Framework\\Headers" REGULAR_EXPRESSION ".*/orthanc/(Core|Plugins)/.*h")
+
+  source_group("Stone Library\\Sources" REGULAR_EXPRESSION ".*/orthanc-stone/.*cpp")
+  source_group("Stone Library\\Headers" REGULAR_EXPRESSION ".*/orthanc-stone/.*hpp")
+  source_group("Stone Library\\Headers" REGULAR_EXPRESSION ".*/orthanc-stone/.*h")
+
+  source_group("Stone Samples\\Source" REGULAR_EXPRESSION ".*orthanc-stone/Samples/.*\\.cpp")
+  source_group("Stone Samples\\Headers" REGULAR_EXPRESSION ".*orthanc-stone/Samples/.*\\.h")
+
+  source_group("ThirdParty\\cairo" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/cairo[^/]*/.*")
+  source_group("ThirdParty\\pixman" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/pixman[^/]*/.*")
+  source_group("ThirdParty\\base64" REGULAR_EXPRESSION ".*ThirdParty/base64.*")
+  source_group("ThirdParty\\SDL2" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/SDL2.*")
+  source_group("ThirdParty\\glew" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/glew.*")
+  source_group("AUTOGENERATED" REGULAR_EXPRESSION ".*${CMAKE_BINARY_DIR}/AUTOGENERATED/.*")
+  source_group("ThirdParty\\minizip" REGULAR_EXPRESSION ".*ThirdParty/minizip/.*")
+  source_group("ThirdParty\\md5" REGULAR_EXPRESSION ".*ThirdParty/md5/.*")
+endmacro()
+