diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt
index 0d72d5511a..7ffa8c7796 100644
--- a/Modules/Core/CMakeLists.txt
+++ b/Modules/Core/CMakeLists.txt
@@ -1,78 +1,87 @@
 set(TOOL_CPPS "")
 
 # temporary suppress warnings in the following files until image accessors are fully integrated.
 set_source_files_properties( src/DataManagement/mitkImage.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS )
 set_source_files_properties( src/Controllers/mitkSliceNavigationController.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS )
 
 #if(MSVC)
 #  set(optional_private_package_depends psapi)
 #endif()
 
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1)
+  set(optional_public_target_depends stdc++fs)
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
+  set(optional_public_target_depends c++fs)
+endif()
+
 mitk_create_module(
   INCLUDE_DIRS
     PUBLIC
       ${MITK_BINARY_DIR}
     PRIVATE
       src/Algorithms
       src/Controllers
       src/DataManagement
       src/Interactions
       src/IO
       src/Rendering
   DEPENDS
     PUBLIC
       mbilog
       CppMicroServices
   PACKAGE_DEPENDS
     PUBLIC
       Boost
       ITK|IOImageBase+SpatialObjects+Statistics
       #ITK|Statistics+Transform
       VTK|FiltersTexture+FiltersParallel+ImagingStencil+ImagingMath+InteractionStyle+RenderingOpenGL2+RenderingVolumeOpenGL2+RenderingFreeType+RenderingLabel+InteractionWidgets+IOGeometry+IOXML
     PRIVATE
       ITK|IOBioRad+IOBMP+IOBruker+IOCSV+IOGDCM+IOGE+IOGIPL+IOHDF5+IOIPL+IOJPEG+IOJPEG2000+IOLSM+IOMesh+IOMeta+IOMINC+IOMRC+IONIFTI+IONRRD+IOPNG+IOSiemens+IOSpatialObjects+IOStimulate+IOTIFF+IOTransformBase+IOTransformHDF5+IOTransformInsightLegacy+IOTransformMatlab+IOVTK+IOXML
       nlohmann_json
       tinyxml2
       ${optional_private_package_depends}
+  TARGET_DEPENDS
+    PUBLIC
+      ${optional_public_target_depends}
   # Do not automatically create CppMicroServices initialization code.
   # Because the VTK "auto-init" functionality injects file-local static
   # initialization code in every cpp file which includes a VTK header,
   # static initialization order becomes an issue again. For the Mitk
   # core library, we need to ensure that the VTK static initialization stuff
   # happens before the CppMicroServices initialization, since the latter
   # might already use VTK code which needs to access VTK object factories.
   # Hence, CppMicroServices initialization code is placed manually within
   # the mitkCoreActivator.cpp file.
   NO_INIT
 )
 if(NOT TARGET ${MODULE_TARGET})
   message(SEND_ERROR "Core target ${MODULE_TARGET} does not exist")
 endif()
 
 function(_itk_create_factory_register_manager)
   # In MITK_ITK_Config.cmake, we do *not* include ITK_USE_FILE, which
   # prevents multiple registrations/unregistrations of ITK IO factories
   # during library loading/unloading (of MITK libraries). However, we need
   # "one" place where the IO factories are registered at
   # least once. This could be the application executable, but every executable would
   # need to take care of that itself. Instead, we allow the auto registration in the
   # Mitk Core library.
   set(NO_DIRECTORY_SCOPED_ITK_COMPILE_DEFINITION 1)
   find_package(ITK)
   include(${ITK_USE_FILE})
 
   if(NOT ITK_NO_IO_FACTORY_REGISTER_MANAGER)
     # We manually add the define which will be of target scope. MITK
     # patches ITK_USE_FILE to remove the directory scoped compile
     # definition since it would be propagated to other targets in the
     # same directory scope but these targets might want to *not*
     # use the ITK factory manager stuff.
     target_compile_definitions(${MODULE_TARGET} PRIVATE ITK_IO_FACTORY_REGISTER_MANAGER)
   endif()
 endfunction()
 _itk_create_factory_register_manager()
 
 if(BUILD_TESTING)
   add_subdirectory(TestingHelper)
   add_subdirectory(test)
 endif()
diff --git a/Modules/Core/include/mitkFileSystem.h b/Modules/Core/include/mitkFileSystem.h
new file mode 100644
index 0000000000..b23d69df0a
--- /dev/null
+++ b/Modules/Core/include/mitkFileSystem.h
@@ -0,0 +1,24 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#ifndef mitkFileSystem_h
+#define mitkFileSystem_h
+
+#if __has_include(<filesystem>)
+  #include <filesystem>
+  namespace fs = std::filesystem;
+#elif __has_include(<experimental/filesystem>)
+  #include <experimental/filesystem>
+  namespace fs = std::experimental::filesystem;
+#endif
+
+#endif
diff --git a/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp b/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
index 231f8d4aed..ce8653ac5d 100644
--- a/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
+++ b/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
@@ -1,75 +1,75 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkMultilabelIOMimeTypes.h"
 #include <mitkIOMimeTypes.h>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 #include <fstream>
 
 #include <nlohmann/json.hpp>
 
 mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::MitkSegmentationTaskListMimeType()
   : CustomMimeType(SEGMENTATIONTASKLIST_MIMETYPE_NAME())
 {
   this->AddExtension("json");
   this->SetCategory("MITK Segmentation Task List");
   this->SetComment("MITK Segmentation Task List");
 }
 
 bool mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::AppliesTo(const std::string& path) const
 {
   bool result = CustomMimeType::AppliesTo(path);
 
-  if (!std::filesystem::exists(path)) // T18572
+  if (!fs::exists(path)) // T18572
     return result;
 
   std::ifstream file(path);
 
   if (!file.is_open())
     return false;
 
   auto json = nlohmann::json::parse(file, nullptr, false);
 
   if (json.is_discarded() || !json.is_object())
     return false;
 
   if ("MITK Segmentation Task List" != json.value("FileFormat", ""))
     return false;
 
   if (1 != json.value<int>("Version", 0))
     return false;
 
   return true;
 }
 
 mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType* mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::Clone() const
 {
   return new MitkSegmentationTaskListMimeType(*this);
 }
 
 mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType mitk::MitkMultilabelIOMimeTypes::SEGMENTATIONTASKLIST_MIMETYPE()
 {
   return MitkSegmentationTaskListMimeType();
 }
 
 std::string mitk::MitkMultilabelIOMimeTypes::SEGMENTATIONTASKLIST_MIMETYPE_NAME()
 {
   return IOMimeTypes::DEFAULT_BASE_NAME() + ".segmentationtasklist";
 }
 
 std::vector<mitk::CustomMimeType*> mitk::MitkMultilabelIOMimeTypes::Get()
 {
   std::vector<CustomMimeType*> mimeTypes;
   mimeTypes.push_back(SEGMENTATIONTASKLIST_MIMETYPE().Clone());
   return mimeTypes;
 }
diff --git a/Modules/Multilabel/autoload/IO/mitkSegmentationTaskListIO.cpp b/Modules/Multilabel/autoload/IO/mitkSegmentationTaskListIO.cpp
index 6afa7c5a81..e883c20426 100644
--- a/Modules/Multilabel/autoload/IO/mitkSegmentationTaskListIO.cpp
+++ b/Modules/Multilabel/autoload/IO/mitkSegmentationTaskListIO.cpp
@@ -1,267 +1,267 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkSegmentationTaskListIO.h"
 #include "mitkMultilabelIOMimeTypes.h"
 
 #include <mitkSegmentationTaskList.h>
 
 #include <nlohmann/json.hpp>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 #include <fstream>
 
 namespace mitk
 {
   void to_json(nlohmann::json& json, const SegmentationTaskList::Task& task)
   {
     if (task.HasName())
       json["Name"] = task.GetName();
 
     if (task.HasDescription())
       json["Description"] = task.GetDescription();
 
     if (task.HasImage())
       json["Image"] = task.GetImage().string();
 
     if (task.HasSegmentation())
       json["Segmentation"] = task.GetSegmentation().string();
 
     if (task.HasLabelName())
       json["LabelName"] = task.GetLabelName();
 
     if (task.HasLabelNameSuggestions())
       json["LabelNameSuggestions"] = task.GetLabelNameSuggestions().string();
 
     if (task.HasPreset())
       json["Preset"] = task.GetPreset().string();
 
     if (task.HasResult())
       json["Result"] = task.GetResult().string();
 
     if (task.HasDynamic())
       json["Dynamic"] = task.GetDynamic();
   }
 
   void from_json(const nlohmann::json& json, SegmentationTaskList::Task& task)
   {
     auto iter = json.find("Name");
 
     if (iter != json.end())
       task.SetName(json["Name"].get<std::string>());
 
     iter = json.find("Description");
 
     if (iter != json.end())
       task.SetDescription(json["Description"].get<std::string>());
 
     iter = json.find("Image");
 
     if (iter != json.end())
       task.SetImage(json["Image"].get<std::string>());
 
     iter = json.find("Segmentation");
 
     if (iter != json.end())
       task.SetSegmentation(json["Segmentation"].get<std::string>());
 
     iter = json.find("LabelName");
 
     if (iter != json.end())
       task.SetLabelName(json["LabelName"].get<std::string>());
 
     iter = json.find("LabelNameSuggestions");
 
     if (iter != json.end())
       task.SetLabelNameSuggestions(json["LabelNameSuggestions"].get<std::string>());
 
     iter = json.find("Preset");
 
     if (iter != json.end())
       task.SetPreset(json["Preset"].get<std::string>());
 
     iter = json.find("Result");
 
     if (iter != json.end())
       task.SetResult(json["Result"].get<std::string>());
 
     iter = json.find("Dynamic");
 
     if (iter != json.end())
       task.SetDynamic(json["Dynamic"].get<bool>());
   }
 }
 
 mitk::SegmentationTaskListIO::SegmentationTaskListIO()
   : AbstractFileIO(SegmentationTaskList::GetStaticNameOfClass(), MitkMultilabelIOMimeTypes::SEGMENTATIONTASKLIST_MIMETYPE(), "MITK Segmentation Task List")
 {
   this->RegisterService();
 }
 
 std::vector<mitk::BaseData::Pointer> mitk::SegmentationTaskListIO::DoRead()
 {
   auto* stream = this->GetInputStream();
   std::ifstream fileStream;
 
   if (nullptr == stream)
   {
     auto filename = this->GetInputLocation();
 
-    if (filename.empty() || !std::filesystem::exists(filename))
+    if (filename.empty() || !fs::exists(filename))
       mitkThrow() << "Invalid or nonexistent filename: \"" << filename << "\"!";
 
     fileStream.open(filename);
 
     if (!fileStream.is_open())
       mitkThrow() << "Could not open file \"" << filename << "\" for reading!";
 
     stream = &fileStream;
   }
 
   nlohmann::json json;
 
   try
   {
     json = nlohmann::json::parse(*stream);
   }
   catch (const nlohmann::json::exception& e)
   {
     mitkThrow() << e.what();
   }
 
   if (!json.is_object())
     mitkThrow() << "Unknown file format (expected JSON object as root)!";
 
   if ("MITK Segmentation Task List" != json.value("FileFormat", ""))
     mitkThrow() << "Unknown file format (expected \"MITK Segmentation Task List\")!";
 
   if (1 != json.value<int>("Version", 0))
     mitkThrow() << "Unknown file format version (expected \"1\")!";
 
   if (!json.contains("Tasks") || !json["Tasks"].is_array())
     mitkThrow() << "Tasks array not found!";
 
   auto segmentationTaskList = SegmentationTaskList::New();
 
   if (json.contains("Name"))
     segmentationTaskList->SetProperty("name", StringProperty::New(json["Name"].get<std::string>()));
 
   try
   {
     if (json.contains("Defaults"))
     {
       segmentationTaskList->SetDefaults(json["Defaults"].get<SegmentationTaskList::Task>());
 
       if (segmentationTaskList->GetDefaults().HasResult())
         mitkThrow() << "Defaults must not contain \"Result\"!";
     }
 
     for (const auto& task : json["Tasks"])
     {
       auto i = segmentationTaskList->AddTask(task.get<SegmentationTaskList::Task>());
 
       if (!segmentationTaskList->HasImage(i))
         mitkThrow() << "Task " << i << " must contain \"Image\"!";
 
-      std::filesystem::path imagePath(segmentationTaskList->GetImage(i));
+      fs::path imagePath(segmentationTaskList->GetImage(i));
 
       if (imagePath.is_relative())
       {
         auto inputLocation = this->GetInputLocation();
 
         /* If we have access to properties, we are reading from an MITK scene
          * file. In this case, paths are still relative to the original input
          * location, which is preserved in the properties.
          */
 
         const auto* properties = this->GetProperties();
 
         if (properties != nullptr)
           properties->GetStringProperty("MITK.IO.reader.inputlocation", inputLocation);
 
-        imagePath = std::filesystem::path(inputLocation).remove_filename() / imagePath;
+        imagePath = fs::path(inputLocation).remove_filename() / imagePath;
       }
 
-      if (!std::filesystem::exists(imagePath))
+      if (!fs::exists(imagePath))
         mitkThrow() << "Referenced image \"" << imagePath << "\" in task " << i << " does not exist!";
 
       if (!segmentationTaskList->HasResult(i))
         mitkThrow() << "Task " << i << " must contain \"Result\"!";
     }
   }
   catch (const nlohmann::json::type_error& e)
   {
     mitkThrow() << e.what();
   }
 
   std::vector<BaseData::Pointer> result;
   result.push_back(segmentationTaskList.GetPointer());
 
   return result;
 }
 
 void mitk::SegmentationTaskListIO::Write()
 {
   auto segmentationTaskList = dynamic_cast<const SegmentationTaskList*>(this->GetInput());
 
   if (nullptr == segmentationTaskList)
     mitkThrow() << "Invalid input for writing!";
 
   if (segmentationTaskList->GetNumberOfTasks() == 0)
     mitkThrow() << "No tasks found!";
 
   auto* stream = this->GetOutputStream();
   std::ofstream fileStream;
 
   if (nullptr == stream)
   {
     auto filename = this->GetOutputLocation();
 
     if (filename.empty())
       mitkThrow() << "Neither an output stream nor an output filename was specified!";
 
     fileStream.open(filename);
 
     if (!fileStream.is_open())
       mitkThrow() << "Could not open file \"" << filename << "\" for writing!";
 
     stream = &fileStream;
   }
 
   if (!stream->good())
     mitkThrow() << "Stream for writing is not good!";
 
   nlohmann::ordered_json json = {
     { "FileFormat", "MITK Segmentation Task List" },
     { "Version", 1 },
     { "Name", segmentationTaskList->GetProperty("name")->GetValueAsString() }
   };
 
   nlohmann::json defaults = segmentationTaskList->GetDefaults();
 
   if (!defaults.is_null())
     json["Defaults"] = defaults;
 
   nlohmann::json tasks;
 
   for (const auto& task : *segmentationTaskList)
     tasks.push_back(task);
 
   json["Tasks"] = tasks;
 
   *stream << std::setw(2) << json << std::endl;
 }
 
 mitk::SegmentationTaskListIO* mitk::SegmentationTaskListIO::IOClone() const
 {
   return new SegmentationTaskListIO(*this);
 }
diff --git a/Modules/Multilabel/mitkSegmentationTaskList.cpp b/Modules/Multilabel/mitkSegmentationTaskList.cpp
index a1a844bc8a..823925609e 100644
--- a/Modules/Multilabel/mitkSegmentationTaskList.cpp
+++ b/Modules/Multilabel/mitkSegmentationTaskList.cpp
@@ -1,174 +1,174 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkSegmentationTaskList.h"
 
 #include <mitkIOUtil.h>
 #include <mitkProperties.h>
 
 mitk::SegmentationTaskList::Task::Task()
   : m_Defaults(nullptr)
 {
 }
 
 mitk::SegmentationTaskList::Task::~Task()
 {
 }
 
 void mitk::SegmentationTaskList::Task::SetDefaults(const Task* defaults)
 {
   m_Defaults = defaults;
 }
 
 mitk::SegmentationTaskList::SegmentationTaskList()
 {
   // A base data cannot be serialized if empty. To be not considered empty its
   // geometry must consist of at least one time step. However, a segmentation
   // task would then appear as invisible spacial object in a scene. This can
   // be prevented by excluding it from the scene's bounding box calculations.
   this->GetTimeGeometry()->Expand(1);
   this->SetProperty("includeInBoundingBox", BoolProperty::New(false));
 }
 
 mitk::SegmentationTaskList::SegmentationTaskList(const Self& other)
   : BaseData(other)
 {
 }
 
 mitk::SegmentationTaskList::~SegmentationTaskList()
 {
 }
 
 size_t mitk::SegmentationTaskList::GetNumberOfTasks() const
 {
   return m_Tasks.size();
 }
 
 size_t mitk::SegmentationTaskList::AddTask(const Task& subtask)
 {
   m_Tasks.push_back(subtask);
   m_Tasks.back().SetDefaults(&m_Defaults);
   return m_Tasks.size() - 1;
 }
 
 const mitk::SegmentationTaskList::Task* mitk::SegmentationTaskList::GetTask(size_t index) const
 {
   return &m_Tasks.at(index);
 }
 
 mitk::SegmentationTaskList::Task* mitk::SegmentationTaskList::GetTask(size_t index)
 {
   return &m_Tasks.at(index);
 }
 
 const mitk::SegmentationTaskList::Task& mitk::SegmentationTaskList::GetDefaults() const
 {
   return m_Defaults;
 }
 
 void mitk::SegmentationTaskList::SetDefaults(const Task& defaults)
 {
   m_Defaults = defaults;
 
   for (auto& subtask : m_Tasks)
     subtask.SetDefaults(&m_Defaults);
 }
 
 bool mitk::SegmentationTaskList::IsDone() const
 {
   for (size_t i = 0; i < m_Tasks.size(); ++i)
   {
     if (!this->IsDone(i))
       return false;
   }
 
   return true;
 }
 
 bool mitk::SegmentationTaskList::IsDone(size_t index) const
 {
-  return std::filesystem::exists(this->GetAbsolutePath(m_Tasks.at(index).GetResult()));
+  return fs::exists(this->GetAbsolutePath(m_Tasks.at(index).GetResult()));
 }
 
-std::filesystem::path mitk::SegmentationTaskList::GetInputLocation() const
+fs::path mitk::SegmentationTaskList::GetInputLocation() const
 {
   std::string inputLocation;
   this->GetPropertyList()->GetStringProperty("MITK.IO.reader.inputlocation", inputLocation);
 
   return !inputLocation.empty()
-    ? std::filesystem::path(inputLocation).lexically_normal()
-    : std::filesystem::path();
+    ? fs::path(inputLocation).lexically_normal()
+    : fs::path();
 }
 
-std::filesystem::path mitk::SegmentationTaskList::GetBasePath() const
+fs::path mitk::SegmentationTaskList::GetBasePath() const
 {
   return this->GetInputLocation().remove_filename();
 }
 
-std::filesystem::path mitk::SegmentationTaskList::GetAbsolutePath(const std::filesystem::path& path) const
+fs::path mitk::SegmentationTaskList::GetAbsolutePath(const fs::path& path) const
 {
   if (path.empty())
     return path;
 
   auto normalizedPath = path.lexically_normal();
 
   return !normalizedPath.is_absolute()
     ? this->GetBasePath() / normalizedPath
     : normalizedPath;
 }
 
 void mitk::SegmentationTaskList::SaveTask(size_t index, const BaseData* segmentation)
 {
   if (segmentation == nullptr)
     return;
 
   auto path = this->GetAbsolutePath(this->GetResult(index));
   IOUtil::Save(segmentation, path.string());
 }
 
 std::vector<mitk::SegmentationTaskList::Task>::const_iterator mitk::SegmentationTaskList::begin() const
 {
   return m_Tasks.begin();
 }
 
 std::vector<mitk::SegmentationTaskList::Task>::const_iterator mitk::SegmentationTaskList::end() const
 {
   return m_Tasks.end();
 }
 
 std::vector<mitk::SegmentationTaskList::Task>::iterator mitk::SegmentationTaskList::begin()
 {
   return m_Tasks.begin();
 }
 
 std::vector<mitk::SegmentationTaskList::Task>::iterator mitk::SegmentationTaskList::end()
 {
   return m_Tasks.end();
 }
 
 void mitk::SegmentationTaskList::SetRequestedRegionToLargestPossibleRegion()
 {
 }
 
 bool mitk::SegmentationTaskList::RequestedRegionIsOutsideOfTheBufferedRegion()
 {
   return false;
 }
 
 bool mitk::SegmentationTaskList::VerifyRequestedRegion()
 {
   return true;
 }
 
 void mitk::SegmentationTaskList::SetRequestedRegion(const itk::DataObject*)
 {
 }
diff --git a/Modules/Multilabel/mitkSegmentationTaskList.h b/Modules/Multilabel/mitkSegmentationTaskList.h
index dae82b718e..bc72f6e72c 100644
--- a/Modules/Multilabel/mitkSegmentationTaskList.h
+++ b/Modules/Multilabel/mitkSegmentationTaskList.h
@@ -1,110 +1,110 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef mitkSegmentationTaskList_h
 #define mitkSegmentationTaskList_h
 
 #include <mitkBaseData.h>
 #include <mitkSegmentationTaskListMacros.h>
 
 #include <MitkMultilabelExports.h>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 #include <optional>
 
 namespace mitk
 {
   /** \brief A list of segmentation tasks.
    *
    * See \ref MITKSegmentationTaskListsPage for more information.
    */
   class MITKMULTILABEL_EXPORT SegmentationTaskList : public BaseData
   {
   public:
     class MITKMULTILABEL_EXPORT Task
     {
     public:
       Task();
       ~Task();
 
       void SetDefaults(const Task* defaults);
 
       mitkSegmentationTaskValueMacro(std::string, Name)
       mitkSegmentationTaskValueMacro(std::string, Description)
-      mitkSegmentationTaskValueMacro(std::filesystem::path, Image)
-      mitkSegmentationTaskValueMacro(std::filesystem::path, Segmentation)
+      mitkSegmentationTaskValueMacro(fs::path, Image)
+      mitkSegmentationTaskValueMacro(fs::path, Segmentation)
       mitkSegmentationTaskValueMacro(std::string, LabelName)
-      mitkSegmentationTaskValueMacro(std::filesystem::path, LabelNameSuggestions)
-      mitkSegmentationTaskValueMacro(std::filesystem::path, Preset)
-      mitkSegmentationTaskValueMacro(std::filesystem::path, Result)
+      mitkSegmentationTaskValueMacro(fs::path, LabelNameSuggestions)
+      mitkSegmentationTaskValueMacro(fs::path, Preset)
+      mitkSegmentationTaskValueMacro(fs::path, Result)
       mitkSegmentationTaskValueMacro(bool, Dynamic)
 
     private:
       const Task* m_Defaults;
     };
 
     mitkClassMacro(SegmentationTaskList, BaseData)
     itkFactorylessNewMacro(Self)
     itkCloneMacro(Self)
 
     mitkSegmentationTaskListValueMacro(std::string, Name)
     mitkSegmentationTaskListValueMacro(std::string, Description)
-    mitkSegmentationTaskListValueMacro(std::filesystem::path, Image)
-    mitkSegmentationTaskListValueMacro(std::filesystem::path, Segmentation)
+    mitkSegmentationTaskListValueMacro(fs::path, Image)
+    mitkSegmentationTaskListValueMacro(fs::path, Segmentation)
     mitkSegmentationTaskListValueMacro(std::string, LabelName)
-    mitkSegmentationTaskListValueMacro(std::filesystem::path, LabelNameSuggestions)
-    mitkSegmentationTaskListValueMacro(std::filesystem::path, Preset)
-    mitkSegmentationTaskListValueMacro(std::filesystem::path, Result)
+    mitkSegmentationTaskListValueMacro(fs::path, LabelNameSuggestions)
+    mitkSegmentationTaskListValueMacro(fs::path, Preset)
+    mitkSegmentationTaskListValueMacro(fs::path, Result)
     mitkSegmentationTaskListValueMacro(bool, Dynamic)
 
     size_t GetNumberOfTasks() const;
     size_t AddTask(const Task& subtask);
     const Task* GetTask(size_t index) const;
     Task* GetTask(size_t index);
 
     const Task& GetDefaults() const;
     void SetDefaults(const Task& defaults);
 
     bool IsDone() const;
     bool IsDone(size_t index) const;
 
-    std::filesystem::path GetInputLocation() const;
-    std::filesystem::path GetBasePath() const;
-    std::filesystem::path GetAbsolutePath(const std::filesystem::path& path) const;
+    fs::path GetInputLocation() const;
+    fs::path GetBasePath() const;
+    fs::path GetAbsolutePath(const fs::path& path) const;
 
     void SaveTask(size_t index, const BaseData* segmentation);
 
     std::vector<Task>::const_iterator begin() const;
     std::vector<Task>::const_iterator end() const;
 
     std::vector<Task>::iterator begin();
     std::vector<Task>::iterator end();
 
     void SetRequestedRegionToLargestPossibleRegion() override;
     bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
     bool VerifyRequestedRegion() override;
     void SetRequestedRegion(const itk::DataObject*) override;
 
   protected:
     mitkCloneMacro(Self)
 
     SegmentationTaskList();
     SegmentationTaskList(const Self& other);
     ~SegmentationTaskList() override;
 
   private:
     Task m_Defaults;
     std::vector<Task> m_Tasks;
   };
 }
 
 #endif
diff --git a/Modules/SceneSerialization/src/mitkSceneReaderV1.cpp b/Modules/SceneSerialization/src/mitkSceneReaderV1.cpp
index c28b3e54ce..6144ccae55 100644
--- a/Modules/SceneSerialization/src/mitkSceneReaderV1.cpp
+++ b/Modules/SceneSerialization/src/mitkSceneReaderV1.cpp
@@ -1,463 +1,463 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkSceneReaderV1.h"
 #include "Poco/Path.h"
 #include "mitkBaseRenderer.h"
 #include "mitkIOUtil.h"
 #include "mitkProgressBar.h"
 #include "mitkPropertyListDeserializer.h"
 #include "mitkSerializerMacros.h"
 #include <mitkUIDManipulator.h>
 #include <mitkRenderingModeProperty.h>
 #include <tinyxml2.h>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 #include <map>
 
 MITK_REGISTER_SERIALIZER(SceneReaderV1)
 
 namespace
 {
   typedef std::pair<mitk::DataNode::Pointer, std::list<std::string>> NodesAndParentsPair;
 
   bool NodeSortByLayerIsLessThan(const NodesAndParentsPair &left, const NodesAndParentsPair &right)
   {
     if (left.first.IsNotNull() && right.first.IsNotNull())
     {
       int leftLayer;
       int rightLayer;
       if (left.first->GetIntProperty("layer", leftLayer) && right.first->GetIntProperty("layer", rightLayer))
       {
         return leftLayer < rightLayer;
       }
       else
       {
         // fall back to name sort
         return left.first->GetName() < right.first->GetName();
       }
     }
 
     // in all other cases, fall back to stupid pointer comparison
     // this is not reasonable but at least answers the sorting
     // question clearly
     return left.first.GetPointer() < right.first.GetPointer();
   }
 
   // This is a workaround until we are able to save time-related information in an
   // actual file format of surfaces.
   void ApplyProportionalTimeGeometryProperties(mitk::BaseData* data)
   {
     auto* geometry = dynamic_cast<mitk::ProportionalTimeGeometry*>(data->GetTimeGeometry());
 
     if (nullptr == geometry)
       return;
 
     auto properties = data->GetPropertyList();
     float value = 0.0f;
 
     if (properties->GetFloatProperty("ProportionalTimeGeometry.FirstTimePoint", value))
     {
       if (value == -std::numeric_limits<float>::infinity())
         value = std::numeric_limits<float>::lowest();
 
       geometry->SetFirstTimePoint(value);
     }
 
     if (properties->GetFloatProperty("ProportionalTimeGeometry.StepDuration", value))
       geometry->SetStepDuration(value);
   }
 
-  mitk::PropertyList::Pointer DeserializeProperties(const tinyxml2::XMLElement *propertiesElement, const std::filesystem::path& basePath)
+  mitk::PropertyList::Pointer DeserializeProperties(const tinyxml2::XMLElement *propertiesElement, const fs::path& basePath)
   {
     if (propertiesElement == nullptr)
       return nullptr;
 
-    std::filesystem::path path(propertiesElement->Attribute("file"));
+    fs::path path(propertiesElement->Attribute("file"));
 
     if (path.empty())
       return nullptr;
 
     if (!basePath.empty())
       path = basePath / path;
 
     auto deserializer = mitk::PropertyListDeserializer::New();
     deserializer->SetFilename(path.string());
     deserializer->Deserialize();
 
     return deserializer->GetOutput();
   }
 }
 
 bool mitk::SceneReaderV1::LoadScene(tinyxml2::XMLDocument &document, const std::string &workingDirectory, DataStorage *storage)
 {
   assert(storage);
   bool error(false);
 
   // TODO prepare to detect errors (such as cycles) from wrongly written or edited xml files
 
   // Get number of elements to initialze progress bar
   //   1. if there is a <data type="..." file="..."> element,
   //        - construct a name for the appropriate serializer
   //        - try to instantiate this serializer via itk object factory
   //        - if serializer could be created, use it to read the file into a BaseData object
   //        - if successful, call the new node's SetData(..)
 
   // create a node for the tag "data" and test if node was created
   typedef std::vector<mitk::DataNode::Pointer> DataNodeVector;
   DataNodeVector DataNodes;
   unsigned int listSize = 0;
   for (auto *element = document.FirstChildElement("node"); element != nullptr;
        element = element->NextSiblingElement("node"))
   {
     ++listSize;
   }
 
   ProgressBar::GetInstance()->AddStepsToDo(listSize * 2);
 
   // Deserialize base data properties before reading the actual data to be
   // able to provide them as read-only meta data to the data reader.
   std::map<std::string, PropertyList::Pointer> baseDataPropertyLists;
 
   for (auto *nodeElement = document.FirstChildElement("node"); nodeElement != nullptr;
        nodeElement = nodeElement->NextSiblingElement("node"))
   {
     const auto *uid = nodeElement->Attribute("UID");
 
     if (uid == nullptr)
       continue;
 
     auto *dataElement = nodeElement->FirstChildElement("data");
 
     if (dataElement != nullptr)
     {
       auto properties = DeserializeProperties(dataElement->FirstChildElement("properties"), workingDirectory);
 
       if (properties.IsNotNull())
         baseDataPropertyLists[uid] = properties;
     }
   }
 
   for (auto *element = document.FirstChildElement("node"); element != nullptr;
        element = element->NextSiblingElement("node"))
   {
     mitk::PropertyList* properties = nullptr;
     const auto *uid = element->Attribute("UID");
 
     if (uid != nullptr)
     {
       auto iter = baseDataPropertyLists.find(uid);
 
       if (iter != baseDataPropertyLists.end())
         properties = iter->second;
     }
 
     const auto *dataElement = element->FirstChildElement("data");
     auto dataNode = this->LoadBaseDataFromDataTag(dataElement, properties, workingDirectory, error);
 
     if (dataNode.IsNull())
       continue;
 
     auto* baseData = dataNode->GetData();
 
     if (baseData != nullptr && properties != nullptr)
     {
       baseData->SetPropertyList(properties);
       ApplyProportionalTimeGeometryProperties(baseData);
     }
 
     DataNodes.push_back(dataNode);
 
     ProgressBar::GetInstance()->Progress();
   }
 
   // iterate all nodes
   // first level nodes should be <node> elements
   auto nit = DataNodes.begin();
   for (auto *element = document.FirstChildElement("node"); element != nullptr || nit != DataNodes.end();
        element = element->NextSiblingElement("node"), ++nit)
   {
     mitk::DataNode::Pointer node = *nit;
 
     //   1. check child nodes
     const char *uida = element->Attribute("UID");
     std::string uid("");
 
     if (uida)
     {
       uid = uida;
       m_NodeForID[uid] = node.GetPointer();
       m_IDForNode[node.GetPointer()] = uid;
     }
     else
     {
       MITK_ERROR << "No UID found for current node. Node will have no parents.";
       error = true;
     }
 
     //   2. if there are <properties> nodes,
     //        - instantiate the appropriate PropertyListDeSerializer
     //        - use them to construct PropertyList objects
     //        - add these properties to the node (if necessary, use renderwindow name)
     bool success = DecorateNodeWithProperties(node, element, workingDirectory);
     if (!success)
     {
       MITK_ERROR << "Could not load properties for node.";
       error = true;
     }
 
     // remember node for later adding to DataStorage
     m_OrderedNodePairs.push_back(std::make_pair(node, std::list<std::string>()));
 
     //   3. if there are <source> elements, remember parent objects
     for (auto *source = element->FirstChildElement("source"); source != nullptr;
          source = source->NextSiblingElement("source"))
     {
       const char *sourceUID = source->Attribute("UID");
       if (sourceUID)
       {
         m_OrderedNodePairs.back().second.push_back(std::string(sourceUID));
       }
     }
 
     ProgressBar::GetInstance()->Progress();
   } // end for all <node>
 
   // sort our nodes by their "layer" property
   // (to be inserted in that order)
   m_OrderedNodePairs.sort(&NodeSortByLayerIsLessThan);
 
   // remove all unknown parent UIDs
   for (auto nodesIter = m_OrderedNodePairs.begin(); nodesIter != m_OrderedNodePairs.end();
        ++nodesIter)
   {
     for (auto parentsIter = nodesIter->second.begin();
          parentsIter != nodesIter->second.end();)
     {
       if (m_NodeForID.find(*parentsIter) == m_NodeForID.end())
       {
         parentsIter = nodesIter->second.erase(parentsIter);
         MITK_WARN << "Found a DataNode with unknown parents. Will add it to DataStorage without any parent objects.";
         error = true;
       }
       else
       {
         ++parentsIter;
       }
     }
   }
 
   // repeat the following loop ...
   //   ... for all created nodes
   unsigned int lastMapSize(0);
   while (lastMapSize !=
          m_OrderedNodePairs
            .size()) // this is to prevent infinite loops; each iteration must at least add one node to DataStorage
   {
     lastMapSize = m_OrderedNodePairs.size();
 
     // iterate (layer) ordered nodes backwards
     // we insert the highest layers first
     for (auto nodesIter = m_OrderedNodePairs.begin(); nodesIter != m_OrderedNodePairs.end();
          ++nodesIter)
     {
       bool addThisNode(true);
 
       // if any parent node is not yet in DataStorage, skip node for now and check later
       for (auto parentsIter = nodesIter->second.begin();
            parentsIter != nodesIter->second.end();
            ++parentsIter)
       {
         if (!storage->Exists(m_NodeForID[*parentsIter]))
         {
           addThisNode = false;
           break;
         }
       }
 
       if (addThisNode)
       {
         DataStorage::SetOfObjects::Pointer parents = DataStorage::SetOfObjects::New();
         for (auto parentsIter = nodesIter->second.begin();
              parentsIter != nodesIter->second.end();
              ++parentsIter)
         {
           parents->push_back(m_NodeForID[*parentsIter]);
         }
 
         // if all parents are found in datastorage (or are unknown), add node to DataStorage
         storage->Add(nodesIter->first, parents);
 
         // remove this node from m_OrderedNodePairs
         m_OrderedNodePairs.erase(nodesIter);
 
         // break this for loop because iterators are probably invalid
         break;
       }
     }
   }
 
   // All nodes that are still in m_OrderedNodePairs at this point are not part of a proper directed graph structure.
   // We'll add such nodes without any parent information.
   for (auto nodesIter = m_OrderedNodePairs.begin(); nodesIter != m_OrderedNodePairs.end();
        ++nodesIter)
   {
     storage->Add(nodesIter->first);
     MITK_WARN << "Encountered node that is not part of a directed graph structure. Will be added to DataStorage "
                  "without parents.";
     error = true;
   }
 
   return !error;
 }
 
 mitk::DataNode::Pointer mitk::SceneReaderV1::LoadBaseDataFromDataTag(const tinyxml2::XMLElement *dataElement,
                                                                      const PropertyList *properties,
                                                                      const std::string &workingDirectory,
                                                                      bool &error)
 {
   DataNode::Pointer node;
 
   if (dataElement)
   {
     const char *filename = dataElement->Attribute("file");
     if (filename && strlen(filename) != 0)
     {
       try
       {
         auto baseData = IOUtil::Load(workingDirectory + Poco::Path::separator() + filename, properties);
 
         node = DataNode::New();
         node->SetData(baseData);
       }
       catch (std::exception &e)
       {
         MITK_ERROR << "Error during attempt to read '" << filename << "'. Exception says: " << e.what();
         error = true;
       }
 
       if (node.IsNull())
       {
         MITK_ERROR << "Error during attempt to read '" << filename << "'. Factory returned nullptr object.";
         error = true;
       }
     }
 
     const char* dataUID = dataElement->Attribute("UID");
     if (!error && dataUID != nullptr)
     {
       UIDManipulator manip(node->GetData());
       manip.SetUID(dataUID);
     }
   }
 
   // in case there was no <data> element we create a new empty node (for appending a propertylist later)
   if (node.IsNull())
   {
     node = DataNode::New();
   }
 
   return node;
 }
 
 void mitk::SceneReaderV1::ClearNodePropertyListWithExceptions(DataNode &node, PropertyList &propertyList)
 {
   // Basically call propertyList.Clear(), but implement exceptions (see bug 19354)
   BaseData *data = node.GetData();
 
   PropertyList::Pointer propertiesToKeep = PropertyList::New();
 
   if (dynamic_cast<Image *>(data))
   {
     /*
       Older scene files (before changes of bug 17547) could contain
       a RenderingMode property with value "LevelWindow_Color".
       Since bug 17547 this value has been removed and replaced by
       the default value LookupTable_LevelWindow_Color.
 
       This new default value does only result in "black-to-white"
       CT images (or others) if there is a corresponding lookup
       table. Such a lookup table is provided as a default value
       by the Image mapper. Since that value was never present in
       older scene files, we do well in not removing the new
       default value here. Otherwise the mapper would fall back
       to another default which is all the colors of the rainbow :-(
     */
     BaseProperty::Pointer lutProperty = propertyList.GetProperty("LookupTable");
     propertiesToKeep->SetProperty("LookupTable", lutProperty);
 
     /*
       Older scene files (before changes of T14807) may contain
       multi-component images without the "Image.Displayed Component"
       property.
 
       As the treatment as multi-component image and the corresponding
       visualization options hinges on that property we should not delete
       it, if it was added by the mapper.
 
       This is a fix for the issue reported in T19919.
     */
     BaseProperty::Pointer compProperty = propertyList.GetProperty("Image.Displayed Component");
     if (compProperty.IsNotNull())
     {
       propertiesToKeep->SetProperty("Image.Displayed Component", compProperty);
     }
   }
 
   propertyList.Clear();
 
   propertyList.ConcatenatePropertyList(propertiesToKeep);
 }
 
 bool mitk::SceneReaderV1::DecorateNodeWithProperties(DataNode *node,
                                                      const tinyxml2::XMLElement *nodeElement,
                                                      const std::string &workingDirectory)
 {
   assert(node);
   assert(nodeElement);
   bool error(false);
 
   for (auto *properties = nodeElement->FirstChildElement("properties"); properties != nullptr;
        properties = properties->NextSiblingElement("properties"))
   {
     const char *propertiesfilea(properties->Attribute("file"));
     std::string propertiesfile(propertiesfilea ? propertiesfilea : "");
 
     const char *renderwindowa(properties->Attribute("renderwindow"));
     std::string renderwindow(renderwindowa ? renderwindowa : "");
 
     PropertyList::Pointer propertyList =
       node->GetPropertyList(renderwindow); // DataNode implementation always returns a propertylist
     ClearNodePropertyListWithExceptions(*node, *propertyList);
 
     // use deserializer to construct new properties
     PropertyListDeserializer::Pointer deserializer = PropertyListDeserializer::New();
 
     deserializer->SetFilename(workingDirectory + Poco::Path::separator() + propertiesfile);
     bool success = deserializer->Deserialize();
     error |= !success;
     PropertyList::Pointer readProperties = deserializer->GetOutput();
 
     if (readProperties.IsNotNull())
     {
       propertyList->ConcatenatePropertyList(readProperties, true); // true = replace
     }
     else
     {
       MITK_ERROR << "Property list reader did not return a property list. This is an implementation error. Please tell "
                     "your developer.";
       error = true;
     }
   }
 
   return !error;
 }
diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp
index e089c1d057..5f2f575629 100644
--- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp
+++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp
@@ -1,180 +1,180 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "org_mitk_gui_qt_flow_segmentation_Activator.h"
 
 // Blueberry
 #include <berryISelectionService.h>
 #include <berryIWorkbenchWindow.h>
 
 #include <itksys/SystemTools.hxx>
 
 //MITK
 #include <mitkBaseApplication.h>
 #include <mitkLabelSetImage.h>
 #include <mitkNodePredicateAnd.h>
 #include <mitkNodePredicateNot.h>
 #include <mitkNodePredicateProperty.h>
 #include <mitkNodePredicateDataType.h>
 #include <mitkIOUtil.h>
 
 // Qmitk
 #include "QmitkSegmentationFlowControlView.h"
 
 #include <ui_QmitkSegmentationFlowControlView.h>
 
 // Qt
 #include <QMessageBox>
 #include <QDir>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 
 const std::string QmitkSegmentationFlowControlView::VIEW_ID = "org.mitk.views.flow.control";
 
 QmitkSegmentationFlowControlView::QmitkSegmentationFlowControlView()
     : m_Controls(new Ui::SegmentationFlowControlView),
       m_Parent(nullptr)
 {
   auto notHelperObject = mitk::NodePredicateNot::New(
     mitk::NodePredicateProperty::New("helper object"));
 
   m_SegmentationPredicate = mitk::NodePredicateAnd::New(
     mitk::TNodePredicateDataType<mitk::LabelSetImage>::New(),
     notHelperObject);
 
   m_SegmentationTaskListPredicate = mitk::NodePredicateAnd::New(
     mitk::TNodePredicateDataType<mitk::SegmentationTaskList>::New(),
     notHelperObject);
 }
 
 void QmitkSegmentationFlowControlView::SetFocus()
 {
     m_Controls->btnStoreAndAccept->setFocus();
 }
 
 void QmitkSegmentationFlowControlView::CreateQtPartControl(QWidget* parent)
 {
   // create GUI widgets from the Qt Designer's .ui file
   m_Controls->setupUi(parent);
 
   m_Parent = parent;
 
   using Self = QmitkSegmentationFlowControlView;
 
   connect(m_Controls->btnStoreAndAccept, &QPushButton::clicked, this, &Self::OnAcceptButtonPushed);
   connect(m_Controls->segmentationTaskListWidget, &QmitkSegmentationTaskListWidget::ActiveTaskChanged, this, &Self::OnActiveTaskChanged);
   connect(m_Controls->segmentationTaskListWidget, &QmitkSegmentationTaskListWidget::CurrentTaskChanged, this, &Self::OnCurrentTaskChanged);
 
   m_Controls->segmentationTaskListWidget->setVisible(false);
   m_Controls->labelStored->setVisible(false);
   UpdateControls();
 
   m_OutputDir = QString::fromStdString(mitk::BaseApplication::instance().config().getString("flow.outputdir", itksys::SystemTools::GetCurrentWorkingDirectory()));
   m_OutputDir = QDir::fromNativeSeparators(m_OutputDir);
 
   m_FileExtension = QString::fromStdString(mitk::BaseApplication::instance().config().getString("flow.outputextension", "nrrd"));
 }
 
 void QmitkSegmentationFlowControlView::OnAcceptButtonPushed()
 {
   if (m_Controls->segmentationTaskListWidget->isVisible())
   {
     auto* taskList = m_Controls->segmentationTaskListWidget->GetTaskList();
 
     if (taskList != nullptr)
     {
       auto activeTaskIndex = m_Controls->segmentationTaskListWidget->GetActiveTaskIndex();
 
       if (activeTaskIndex.has_value())
       {
         auto segmentationNode = m_Controls->segmentationTaskListWidget->GetSegmentationDataNode(activeTaskIndex.value());
 
         if (segmentationNode != nullptr)
         {
           QApplication::setOverrideCursor(Qt::BusyCursor);
 
           try
           {
             taskList->SaveTask(activeTaskIndex.value(), segmentationNode->GetData());
             m_Controls->segmentationTaskListWidget->OnUnsavedChangesSaved();
           }
           catch (const mitk::Exception& e)
           {
             MITK_ERROR << e;
           }
 
           QApplication::restoreOverrideCursor();
         }
       }
     }
   }
   else
   {
     auto nodes = this->GetDataStorage()->GetSubset(m_SegmentationPredicate);
 
     for (auto node : *nodes)
     {
       QString outputpath = m_OutputDir + "/" + QString::fromStdString(node->GetName()) + "." + m_FileExtension;
       outputpath = QDir::toNativeSeparators(QDir::cleanPath(outputpath));
       mitk::IOUtil::Save(node->GetData(), outputpath.toStdString());
     }
 
     m_Controls->labelStored->setVisible(true);
   }
 }
 
 void QmitkSegmentationFlowControlView::OnActiveTaskChanged(const std::optional<size_t>&)
 {
   this->UpdateControls();
 }
 
 void QmitkSegmentationFlowControlView::OnCurrentTaskChanged(const std::optional<size_t>&)
 {
   this->UpdateControls();
 }
 
 void QmitkSegmentationFlowControlView::UpdateControls()
 {
   auto dataStorage = this->GetDataStorage();
 
   auto hasTaskList = !dataStorage->GetSubset(m_SegmentationTaskListPredicate)->empty();
   m_Controls->segmentationTaskListWidget->setVisible(hasTaskList);
 
   if (hasTaskList)
   {
     auto activeTaskIsShown = m_Controls->segmentationTaskListWidget->ActiveTaskIsShown();
     m_Controls->btnStoreAndAccept->setEnabled(activeTaskIsShown);
   }
   else
   {
     auto hasSegmentation = !dataStorage->GetSubset(m_SegmentationPredicate)->empty();
     m_Controls->btnStoreAndAccept->setEnabled(hasSegmentation);
   }
 }
 
 void QmitkSegmentationFlowControlView::NodeAdded(const mitk::DataNode* node)
 {
   if (dynamic_cast<const mitk::LabelSetImage*>(node->GetData()) != nullptr)
     this->UpdateControls();
 }
 
 void QmitkSegmentationFlowControlView::NodeChanged(const mitk::DataNode* node)
 {
   if (dynamic_cast<const mitk::LabelSetImage*>(node->GetData()) != nullptr)
     this->UpdateControls();
 }
 
 void QmitkSegmentationFlowControlView::NodeRemoved(const mitk::DataNode* node)
 {
   if (dynamic_cast<const mitk::LabelSetImage*>(node->GetData()) != nullptr)
     this->UpdateControls();
 }
diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationTaskListWidget.cpp b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationTaskListWidget.cpp
index 00a1ec5af0..38e2942b19 100644
--- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationTaskListWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationTaskListWidget.cpp
@@ -1,769 +1,769 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "QmitkSegmentationTaskListWidget.h"
 #include "org_mitk_gui_qt_flow_segmentation_Activator.h"
 
 #include <berryIPreferences.h>
 #include <berryIPreferencesService.h>
 #include <berryPlatform.h>
 
 #include <mitkIDataStorageService.h>
 #include <mitkIOUtil.h>
 #include <mitkLabelSetIOHelper.h>
 #include <mitkLabelSetImageHelper.h>
 #include <mitkNodePredicateDataType.h>
 #include <mitkNodePredicateFunction.h>
 #include <mitkRenderingManager.h>
 #include <mitkSegmentationHelper.h>
 
 #include <QmitkStaticDynamicSegmentationDialog.h>
 #include <QmitkStyleManager.h>
 
 #include <ui_QmitkSegmentationTaskListWidget.h>
 
 #include <QFileSystemWatcher>
 #include <QMessageBox>
 
-#include <filesystem>
+#include <mitkFileSystem.h>
 
 namespace
 {
   berry::IPreferences::Pointer GetSegmentationPreferences()
   {
     return berry::Platform::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentation");
   }
 
   mitk::DataStorage* GetDataStorage()
   {
     auto* pluginContext = org_mitk_gui_qt_flow_segmentation_Activator::GetContext();
     auto dataStorageServiceReference = pluginContext->getServiceReference<mitk::IDataStorageService>();
 
     if (dataStorageServiceReference)
     {
       auto* dataStorageService = pluginContext->getService<mitk::IDataStorageService>(dataStorageServiceReference);
 
       if (dataStorageService != nullptr)
       {
         auto dataStorageReference = dataStorageService->GetDataStorage();
         pluginContext->ungetService(dataStorageServiceReference);
 
         return dataStorageReference->GetDataStorage();
       }
     }
 
     return nullptr;
   }
 
-  std::filesystem::path GetInputLocation(const mitk::BaseData* data)
+  fs::path GetInputLocation(const mitk::BaseData* data)
   {
     std::string result;
 
     if (data != nullptr)
       data->GetPropertyList()->GetStringProperty("MITK.IO.reader.inputlocation", result);
 
     return result;
   }
 
   QString ColorString(const QString& string, const QColor& color, const QColor& backgroundColor = QColor::Invalid)
   {
     if (!color.isValid() && !backgroundColor.isValid())
       return string;
 
     auto result = QStringLiteral("<span style=\"");
     QStringList strings;
 
     if (color.isValid())
       strings << QString("color: %1;").arg(color.name());
 
     if (backgroundColor.isValid())
       strings << QString("background-color: %1;").arg(backgroundColor.name());
 
     result += strings.join(' ') + QString("\">%1</span>").arg(string);
 
     return result;
   }
 }
 
 /* This constructor has three objectives:
  *   1. Do widget initialization that cannot be done in the .ui file
  *   2. Connect signals and slots
  *   3. Explicitly trigger a reset to a valid initial widget state
  */
 QmitkSegmentationTaskListWidget::QmitkSegmentationTaskListWidget(QWidget* parent)
   : QWidget(parent),
     m_Ui(new Ui::QmitkSegmentationTaskListWidget),
     m_FileSystemWatcher(new QFileSystemWatcher(this)),
     m_UnsavedChanges(false)
 {
   m_Ui->setupUi(this);
 
   m_Ui->selectionWidget->SetDataStorage(GetDataStorage());
   m_Ui->selectionWidget->SetSelectionIsOptional(true);
   m_Ui->selectionWidget->SetEmptyInfo(QStringLiteral("Select a segmentation task list"));
   m_Ui->selectionWidget->SetAutoSelectNewNodes(true);
   m_Ui->selectionWidget->SetNodePredicate(mitk::TNodePredicateDataType<mitk::SegmentationTaskList>::New());
 
   m_Ui->progressBar->setStyleSheet(QString("QProgressBar::chunk { background-color: %1; }").arg(QmitkStyleManager::GetIconAccentColor()));
 
   using Self = QmitkSegmentationTaskListWidget;
 
   connect(m_Ui->selectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &Self::OnSelectionChanged);
   connect(m_Ui->previousButton, &QToolButton::clicked, this, &Self::OnPreviousButtonClicked);
   connect(m_Ui->nextButton, &QToolButton::clicked, this, &Self::OnNextButtonClicked);
   connect(m_Ui->loadButton, &QPushButton::clicked, this, &Self::OnLoadButtonClicked);
 
   connect(m_FileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, &Self::OnResultDirectoryChanged);
 
   this->OnSelectionChanged(m_Ui->selectionWidget->GetSelectedNodes());
 }
 
 QmitkSegmentationTaskListWidget::~QmitkSegmentationTaskListWidget()
 {
 }
 
 mitk::SegmentationTaskList* QmitkSegmentationTaskListWidget::GetTaskList() const
 {
   return m_TaskList;
 }
 
 std::optional<size_t> QmitkSegmentationTaskListWidget::GetActiveTaskIndex() const
 {
   return m_ActiveTaskIndex;
 }
 
 std::optional<size_t> QmitkSegmentationTaskListWidget::GetCurrentTaskIndex() const
 {
   return m_CurrentTaskIndex;
 }
 
 void QmitkSegmentationTaskListWidget::OnUnsavedChangesSaved()
 {
   if (m_UnsavedChanges)
   {
     m_UnsavedChanges = false;
 
     if (this->ActiveTaskIsShown())
       this->UpdateDetailsLabel();
   }
 }
 
 /* Make sure that the widget transitions into a valid state whenever the
  * selection changes.
  */
 void QmitkSegmentationTaskListWidget::OnSelectionChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes)
 {
   this->UnloadTasks();
   this->ResetControls();
 
   if (!nodes.empty())
   {
     m_TaskListNode = nodes.front();
     auto taskList = dynamic_cast<mitk::SegmentationTaskList*>(m_TaskListNode->GetData());
 
     if (taskList != nullptr)
     {
       this->OnTaskListChanged(taskList);
       return;
     }
   }
 
   this->SetTaskList(nullptr);
   m_TaskListNode = nullptr;
 }
 
 /* Reset all controls to a default state as a common basis for further
  * adjustments.
  */
 void QmitkSegmentationTaskListWidget::ResetControls()
 {
   m_Ui->progressBar->setEnabled(false);
   m_Ui->progressBar->setFormat("");
   m_Ui->progressBar->setValue(0);
   m_Ui->progressBar->setMaximum(1);
 
   m_Ui->previousButton->setEnabled(false);
   m_Ui->nextButton->setEnabled(false);
 
   this->UpdateLoadButton();
   this->UpdateDetailsLabel();
 }
 
 /* If the segmentation task changed, reset all member variables to expected
  * default values and reset the file system watcher.
  */
 void QmitkSegmentationTaskListWidget::SetTaskList(mitk::SegmentationTaskList* taskList)
 {
   if (m_TaskList != taskList)
   {
     m_TaskList = taskList;
 
     if (taskList != nullptr)
     {
       this->SetCurrentTaskIndex(0);
     }
     else
     {
       this->SetCurrentTaskIndex(std::nullopt);
     }
 
     this->ResetFileSystemWatcher();
   }
 }
 
 void QmitkSegmentationTaskListWidget::ResetFileSystemWatcher()
 {
   auto paths = m_FileSystemWatcher->directories();
 
   if (!paths.empty())
     m_FileSystemWatcher->removePaths(paths);
 
   if (m_TaskList.IsNotNull())
   {
     for (const auto& task : *m_TaskList)
     {
       auto resultPath = m_TaskList->GetAbsolutePath(task.GetResult()).remove_filename();
 
-      if (!std::filesystem::exists(resultPath))
+      if (!fs::exists(resultPath))
       {
         try
         {
-          std::filesystem::create_directories(resultPath);
+          fs::create_directories(resultPath);
         }
-        catch (const std::filesystem::filesystem_error& e)
+        catch (const fs::filesystem_error& e)
         {
           MITK_ERROR << e.what();
         }
       }
 
-      if (std::filesystem::exists(resultPath))
+      if (fs::exists(resultPath))
         m_FileSystemWatcher->addPath(QString::fromStdString(resultPath.string()));
     }
   }
 }
 
 void QmitkSegmentationTaskListWidget::OnResultDirectoryChanged(const QString&)
 {
   // TODO: If a segmentation was modified ("Unsaved changes"), saved ("Done"), and then the file is deleted, the status should be "Unsaved changes" instead of "Not done".
   this->UpdateProgressBar();
   this->UpdateDetailsLabel();
 }
 
 void QmitkSegmentationTaskListWidget::UpdateProgressBar()
 {
   int progress = 0;
 
   for (size_t i = 0; i < m_TaskList->GetNumberOfTasks(); ++i)
   {
     if (m_TaskList->IsDone(i))
       ++progress;
   }
 
   m_Ui->progressBar->setValue(progress);
 }
 
 /* Provided that a valid segmentation task list is currently selected and the
  * widget is in its default state, update all controls accordingly.
  */
 void QmitkSegmentationTaskListWidget::OnTaskListChanged(mitk::SegmentationTaskList* taskList)
 {
   this->SetTaskList(taskList);
 
   const auto numTasks = taskList->GetNumberOfTasks();
 
   m_Ui->progressBar->setMaximum(numTasks);
   m_Ui->progressBar->setFormat(QStringLiteral("%v/%m Task(s) done"));
   m_Ui->progressBar->setEnabled(true);
 
   this->UpdateProgressBar();
 
   m_Ui->loadButton->setEnabled(true);
 
   if (numTasks > 1)
     m_Ui->nextButton->setEnabled(true);
 }
 
 /* If possible, change the currently displayed task to the previous task.
  * Enable/disable navigation buttons according to the task's position.
  */
 void QmitkSegmentationTaskListWidget::OnPreviousButtonClicked()
 {
   const auto maxIndex = m_TaskList->GetNumberOfTasks() - 1;
   auto current = m_CurrentTaskIndex.value();
 
   if (current != 0)
     this->SetCurrentTaskIndex(current - 1);
 
   current = m_CurrentTaskIndex.value();
 
   if (current == 0)
     m_Ui->previousButton->setEnabled(false);
 
   if (current < maxIndex)
     m_Ui->nextButton->setEnabled(true);
 }
 
 /* If possible, change the currently displayed task to the next task.
  * Enable/disable navigation buttons according to the task's position.
  */
 void QmitkSegmentationTaskListWidget::OnNextButtonClicked()
 {
   const auto maxIndex = m_TaskList->GetNumberOfTasks() - 1;
   auto current = m_CurrentTaskIndex.value();
 
   if (current < maxIndex)
     this->SetCurrentTaskIndex(current + 1);
 
   current = m_CurrentTaskIndex.value();
 
   if (current != 0)
     m_Ui->previousButton->setEnabled(true);
 
   if (current >= maxIndex)
     m_Ui->nextButton->setEnabled(false);
 }
 
 /* Update affected controls when the currently displayed task changed.
  */
 void QmitkSegmentationTaskListWidget::OnCurrentTaskChanged()
 {
   this->UpdateLoadButton();
   this->UpdateDetailsLabel();
 }
 
 /* Update the load button according to the currently displayed task.
  */
 void QmitkSegmentationTaskListWidget::UpdateLoadButton()
 {
   auto text = !this->ActiveTaskIsShown()
     ? QStringLiteral("Load task")
     : QStringLiteral("Task");
 
   if (m_CurrentTaskIndex.has_value())
   {
     const auto current = m_CurrentTaskIndex.value();
 
     if (m_TaskList.IsNotNull())
     {
       text += QString(" %1/%2").arg(current + 1).arg(m_TaskList->GetNumberOfTasks());
 
       if (m_TaskList->HasName(current))
         text += QStringLiteral(":\n") + QString::fromStdString(m_TaskList->GetName(current));
     }
 
     m_Ui->loadButton->setDisabled(this->ActiveTaskIsShown());
   }
   else
   {
     m_Ui->loadButton->setEnabled(false);
   }
 
   m_Ui->loadButton->setText(text);
 }
 
 /* Update the details label according to the currently display task.
  * The text is composed of the status of the task and a variable number
  * of text blocks according to the optional values provided by the task.
  */
 void QmitkSegmentationTaskListWidget::UpdateDetailsLabel()
 {
   if (!m_CurrentTaskIndex.has_value())
   {
     m_Ui->detailsLabel->clear();
     return;
   }
 
   const auto current = m_CurrentTaskIndex.value();
   bool isDone = m_TaskList->IsDone(current);
 
   auto details = QString("<p><b>Status: %1</b> / <b>").arg(this->ActiveTaskIsShown()
     ? ColorString("Active", Qt::white, QColor(Qt::green).darker())
     : ColorString("Inactive", Qt::white, QColor(Qt::red).darker()));
 
   if (m_UnsavedChanges && this->ActiveTaskIsShown())
   {
     details += QString("%1</b></p>").arg(ColorString("Unsaved changes", Qt::white, QColor(Qt::red).darker()));
   }
   else
   {
     details += QString("%1</b></p>").arg(isDone
       ? ColorString("Done", Qt::white, QColor(Qt::green).darker())
       : ColorString("Not done", Qt::white, QColor(Qt::red).darker()));
   }
 
   if (m_TaskList->HasDescription(current))
     details += QString("<p><b>Description:</b> %1</p>").arg(QString::fromStdString(m_TaskList->GetDescription(current)));
 
   QStringList stringList;
 
   if (m_TaskList->HasImage(current))
     stringList << QString::fromStdString("<b>Image:</b> " + m_TaskList->GetImage(current).string());
 
   if (m_TaskList->HasSegmentation(current))
     stringList << QString::fromStdString("<b>Segmentation:</b> " + m_TaskList->GetSegmentation(current).string());
 
   if (m_TaskList->HasLabelName(current))
     stringList << QString::fromStdString("<b>Label name:</b> " + m_TaskList->GetLabelName(current));
 
   if (m_TaskList->HasLabelNameSuggestions(current))
     stringList << QString::fromStdString("<b>Label name suggestions:</b> " + m_TaskList->GetLabelNameSuggestions(current).string());
 
   if (m_TaskList->HasPreset(current))
     stringList << QString::fromStdString("<b>Label set preset:</b> " + m_TaskList->GetPreset(current).string());
 
   if (m_TaskList->HasDynamic(current))
     stringList << QString("<b>Segmentation type:</b> %1").arg(m_TaskList->GetDynamic(current) ? "Dynamic" : "Static");
 
   if (!stringList.empty())
     details += QString("<p>%1</p>").arg(stringList.join(QStringLiteral("<br>")));
 
   m_Ui->detailsLabel->setText(details);
 }
 
 /* Load/activate the currently displayed task. Unload all data nodes from
  * previously active tasks first, but spare and reuse the image if possible.
  */
 void QmitkSegmentationTaskListWidget::OnLoadButtonClicked()
 {
   if (!this->HandleUnsavedChanges() || m_UnsavedChanges)
     return;
 
   m_Ui->loadButton->setEnabled(false);
 
   QApplication::setOverrideCursor(Qt::BusyCursor);
   this->LoadTask(this->GetImageDataNode(m_CurrentTaskIndex.value()));
   QApplication::restoreOverrideCursor();
 }
 
 /* If present, return the image data node for the task with the specified
  * index. Otherwise, return nullptr.
  */
 mitk::DataNode* QmitkSegmentationTaskListWidget::GetImageDataNode(size_t index) const
 {
   const auto imagePath = m_TaskList->GetAbsolutePath(m_TaskList->GetImage(index));
 
   auto imageNodes = GetDataStorage()->GetDerivations(m_TaskListNode, mitk::NodePredicateFunction::New([imagePath](const mitk::DataNode* node) {
     return imagePath == GetInputLocation(node->GetData());
   }));
 
   return !imageNodes->empty()
     ? imageNodes->front()
     : nullptr;
 }
 
 /* If present, return the segmentation data node for the task with the
  * specified index. Otherwise, return nullptr.
  */
 mitk::DataNode* QmitkSegmentationTaskListWidget::GetSegmentationDataNode(size_t index) const
 {
   const auto* imageNode = this->GetImageDataNode(index);
 
   if (imageNode != nullptr)
   {
     auto segmentations = GetDataStorage()->GetDerivations(imageNode, mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
 
     if (!segmentations->empty())
       return segmentations->front();
   }
 
   return nullptr;
 }
 
 /* Unload all task data nodes but spare the passed image data node.
  */
 void QmitkSegmentationTaskListWidget::UnloadTasks(const mitk::DataNode* skip)
 {
   this->UnsubscribeFromActiveSegmentation();
 
   if (m_TaskListNode.IsNotNull())
   {
     mitk::DataStorage::Pointer dataStorage = GetDataStorage();
 
     auto imageNodes = dataStorage->GetDerivations(m_TaskListNode, mitk::TNodePredicateDataType<mitk::Image>::New());
 
     for (auto imageNode : *imageNodes)
     {
       dataStorage->Remove(dataStorage->GetDerivations(imageNode, nullptr, false));
 
       if (imageNode != skip)
         dataStorage->Remove(imageNode);
     }
   }
 
   this->SetActiveTaskIndex(std::nullopt);
 }
 
 /* Load/activate the currently displayed task. The task must specify
  * an image. The segmentation is either created from scratch with an optional
  * name for the first label, possibly based on a label set preset specified by
  * the task, or loaded as specified by the task. If a result file does
  * exist, it is chosen as segmentation instead.
  */
 void QmitkSegmentationTaskListWidget::LoadTask(mitk::DataNode::Pointer imageNode)
 {
   this->UnloadTasks(imageNode);
 
   const auto current = m_CurrentTaskIndex.value();
 
   mitk::Image::Pointer image;
   mitk::LabelSetImage::Pointer segmentation;
 
   try
   {
     if (imageNode.IsNull())
     {
       const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetImage(current));
       image = mitk::IOUtil::Load<mitk::Image>(path.string());
     }
 
     const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetResult(current));
 
-    if (std::filesystem::exists(path))
+    if (fs::exists(path))
     {
       segmentation = mitk::IOUtil::Load<mitk::LabelSetImage>(path.string());
     }
     else if (m_TaskList->HasSegmentation(current))
     {
       const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetSegmentation(current));
       segmentation = mitk::IOUtil::Load<mitk::LabelSetImage>(path.string());
     }
   }
   catch (const mitk::Exception&)
   {
     return;
   }
 
   auto dataStorage = GetDataStorage();
 
   if (imageNode.IsNull())
   {
     imageNode = mitk::DataNode::New();
     imageNode->SetData(image);
 
     dataStorage->Add(imageNode, m_TaskListNode);
 
     mitk::RenderingManager::GetInstance()->InitializeViews(image->GetTimeGeometry());
   }
   else
   {
     image = static_cast<mitk::Image*>(imageNode->GetData());
   }
 
   auto name = "Task " + std::to_string(current + 1);
   imageNode->SetName(name);
 
   if (segmentation.IsNull())
   {
     mitk::Image::ConstPointer templateImage = image;
 
     if (templateImage->GetDimension() > 3)
     {
       if (m_TaskList->HasDynamic(current))
       {
         if (!m_TaskList->GetDynamic(current))
           templateImage = mitk::SegmentationHelper::GetStaticSegmentationTemplate(image);
       }
       else
       {
         QmitkStaticDynamicSegmentationDialog dialog(this);
         dialog.SetReferenceImage(templateImage);
         dialog.exec();
 
         templateImage = dialog.GetSegmentationTemplate();
       }
     }
 
     auto segmentationNode = mitk::LabelSetImageHelper::CreateNewSegmentationNode(imageNode, templateImage, name);
     segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
 
     if (m_TaskList->HasPreset(current))
     {
       const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetPreset(current));
       mitk::LabelSetIOHelper::LoadLabelSetImagePreset(path.string(), segmentation);
     }
     else
     {
       auto label = mitk::LabelSetImageHelper::CreateNewLabel(segmentation);
 
       if (m_TaskList->HasLabelName(current))
         label->SetName(m_TaskList->GetLabelName(current));
 
       segmentation->GetActiveLabelSet()->AddLabel(label);
     }
 
     dataStorage->Add(segmentationNode, imageNode);
   }
   else
   {
     auto segmentationNode = mitk::DataNode::New();
     segmentationNode->SetName(name);
     segmentationNode->SetData(segmentation);
 
     dataStorage->Add(segmentationNode, imageNode);
   }
 
   auto prefs = GetSegmentationPreferences();
 
   if (prefs.IsNotNull())
   {
     if (m_TaskList->HasLabelNameSuggestions(current))
     {
       auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetLabelNameSuggestions(current));
 
       prefs->PutBool("default label naming", false);
       prefs->Put("label suggestions", QString::fromStdString(path.string()));
       prefs->PutBool("replace standard suggestions", true);
       prefs->PutBool("suggest once", true);
     }
     else
     {
       prefs->PutBool("default label naming", true);
       prefs->Put("label suggestions", "");
     }
   }
 
   m_UnsavedChanges = false;
 
   this->SetActiveTaskIndex(current);
   this->SubscribeToActiveSegmentation();
 
   this->OnCurrentTaskChanged();
 }
 
 void QmitkSegmentationTaskListWidget::SubscribeToActiveSegmentation()
 {
   if (m_ActiveTaskIndex.has_value())
   {
     auto segmentationNode = this->GetSegmentationDataNode(m_ActiveTaskIndex.value());
 
     if (segmentationNode != nullptr)
     {
       auto segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
 
       auto command = itk::SimpleMemberCommand<QmitkSegmentationTaskListWidget>::New();
       command->SetCallbackFunction(this, &QmitkSegmentationTaskListWidget::OnSegmentationModified);
 
       m_SegmentationModifiedObserverTag = segmentation->AddObserver(itk::ModifiedEvent(), command);
     }
   }
 }
 
 void QmitkSegmentationTaskListWidget::UnsubscribeFromActiveSegmentation()
 {
   if (m_ActiveTaskIndex.has_value() && m_SegmentationModifiedObserverTag.has_value())
   {
     auto segmentationNode = this->GetSegmentationDataNode(m_ActiveTaskIndex.value());
 
     if (segmentationNode != nullptr)
     {
       auto segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
       segmentation->RemoveObserver(m_SegmentationModifiedObserverTag.value());
     }
 
     m_SegmentationModifiedObserverTag.reset();
   }
 }
 
 void QmitkSegmentationTaskListWidget::OnSegmentationModified()
 {
   if (!m_UnsavedChanges)
   {
     m_UnsavedChanges = true;
 
     if (m_ActiveTaskIndex.value() == m_CurrentTaskIndex)
       this->UpdateDetailsLabel();
   }
 }
 
 void QmitkSegmentationTaskListWidget::SetActiveTaskIndex(const std::optional<size_t>& index)
 {
   if (m_ActiveTaskIndex != index)
   {
     m_ActiveTaskIndex = index;
     emit ActiveTaskChanged(m_ActiveTaskIndex);
   }
 }
 
 void QmitkSegmentationTaskListWidget::SetCurrentTaskIndex(const std::optional<size_t>& index)
 {
   if (m_CurrentTaskIndex != index)
   {
     m_CurrentTaskIndex = index;
     this->OnCurrentTaskChanged();
     emit CurrentTaskChanged(m_CurrentTaskIndex);
   }
 }
 
 bool QmitkSegmentationTaskListWidget::ActiveTaskIsShown() const
 {
   return m_ActiveTaskIndex.has_value() && m_CurrentTaskIndex.has_value() && m_ActiveTaskIndex == m_CurrentTaskIndex;
 }
 
 bool QmitkSegmentationTaskListWidget::HandleUnsavedChanges()
 {
   if (m_UnsavedChanges)
   {
     const auto active = m_ActiveTaskIndex.value();
     const auto current = m_CurrentTaskIndex.value();
 
     auto title = QString("Load task %1").arg(current + 1);
 
     if (m_TaskList->HasName(current))
       title += ": " + QString::fromStdString(m_TaskList->GetName(current));
 
     auto text = QString("The currently active task %1 ").arg(active + 1);
 
     if (m_TaskList->HasName(active))
       text += "(" + QString::fromStdString(m_TaskList->GetName(active)) + ") ";
 
     text += "has unsaved changes.";
 
     auto reply = QMessageBox::question(this, title, text, QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
 
     switch (reply)
     {
     case QMessageBox::Save:
       this->SaveActiveTask();
       break;
 
     case QMessageBox::Discard:
       m_UnsavedChanges = false;
       break;
 
     default:
       return false;
     }
   }
 
   return true;
 }
 
 void QmitkSegmentationTaskListWidget::SaveActiveTask()
 {
   if (!m_ActiveTaskIndex.has_value())
     return;
 
   QApplication::setOverrideCursor(Qt::BusyCursor);
 
   try
   {
     const auto active = m_ActiveTaskIndex.value();
     m_TaskList->SaveTask(active, this->GetSegmentationDataNode(active)->GetData());
     this->OnUnsavedChangesSaved();
   }
   catch (const mitk::Exception& e)
   {
     MITK_ERROR << e;
   }
 
   QApplication::restoreOverrideCursor();
 }