diff --git a/CMake/mitkFunctionCreateModule.cmake b/CMake/mitkFunctionCreateModule.cmake index e7c9811ee0..9ec5cd1148 100644 --- a/CMake/mitkFunctionCreateModule.cmake +++ b/CMake/mitkFunctionCreateModule.cmake @@ -1,652 +1,653 @@ ################################################################## # # mitk_create_module # #! Creates a module for the automatic module dependency system within MITK. #! #! Example: #! #! \code #! mitk_create_module( #! DEPENDS PUBLIC MitkCore #! PACKAGE_DEPENDS #! PRIVATE Qt5|Xml+Networking #! PUBLIC ITK|Watershed #! \endcode #! #! The parameter specifies the name of the module which is used #! to create a logical target name. The parameter is optional in case the #! MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME variable evaluates to TRUE. The #! module name will then be derived from the directory name in which this #! function is called. #! #! If set, the following variables will be used to validate the module name: #! #! MITK_MODULE_NAME_REGEX_MATCH The module name must match this regular expression. #! MITK_MODULE_NAME_REGEX_NOT_MATCH The module name must not match this regular expression. #! #! If the MITK_MODULE_NAME_PREFIX variable is set, the module name will be prefixed #! with its contents. #! #! A modules source files are specified in a separate CMake file usually #! called files.cmake, located in the module root directory. The #! mitk_create_module() macro evaluates the following CMake variables #! from the files.cmake file: #! #! - CPP_FILES A list of .cpp files #! - H_FILES A list of .h files without a corresponding .cpp file #! - TXX_FILES A list of .txx files #! - RESOURCE_FILES A list of files (resources) which are embedded into the module #! - MOC_H_FILES A list of Qt header files which should be processed by the MOC #! - UI_FILES A list of .ui Qt UI files #! - QRC_FILES A list of .qrc Qt resource files #! - DOX_FILES A list of .dox Doxygen files #! #! List of variables available after the function is called: #! - MODULE_NAME #! - MODULE_TARGET #! - MODULE_IS_ENABLED #! - MODULE_SUBPROJECTS #! #! \sa mitk_create_executable #! #! Parameters (all optional): #! #! \param The module name (also used as target name) #! \param FILES_CMAKE File name of a CMake file setting source list variables #! (defaults to files.cmake) #! \param VERSION Module version number, e.g. "1.2.0" #! \param AUTOLOAD_WITH A module target name identifying the module which will #! trigger the automatic loading of this module #! \param DEPRECATED_SINCE Marks this modules as deprecated since #! \param DESCRIPTION A description for this module #! #! Multi-value Parameters (all optional): #! #! \param SUBPROJECTS List of CDash labels #! \param INCLUDE_DIRS Include directories for this module: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for include directories is PUBLIC. #! \param DEPENDS List of module dependencies: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for module dependencies is PUBLIC. #! \param PACKAGE_DEPENDS List of public packages dependencies (e.g. Qt, VTK, etc.). #! Package dependencies have the following syntax: #! \verbatim #! [PUBLIC|PRIVATE|INTERFACE] PACKAGE[|COMPONENT1[+COMPONENT2]...] #! \endverbatim #! The default scope for package dependencies is PRIVATE. #! \param ADDITIONAL_LIBS List of additional private libraries linked to this module. #! The folder containing the library will be added to the global list of library search paths. #! \param CPP_FILES List of source files for this module. If the list is non-empty, #! the module does not need to provide a files.cmake file or FILES_CMAKE argument. #! \param H_FILES List of public header files for this module. It is recommended to use #! a files.cmake file instead. #! #! Options (optional) #! #! \param FORCE_STATIC Force building this module as a static library #! \param GCC_DEFAULT_VISIBILITY Do not use gcc visibility flags - all #! symbols will be exported #! \param NO_INIT Do not create CppMicroServices initialization code #! \param NO_FEATURE_INFO Do not create a feature info by calling add_feature_info() #! \param WARNINGS_NO_ERRORS Do not treat compiler warnings as errors # ################################################################## function(mitk_create_module) set(_macro_params VERSION # module version number, e.g. "1.2.0" EXPORT_DEFINE # export macro name for public symbols of this module (DEPRECATED) AUTOLOAD_WITH # a module target name identifying the module which will trigger the # automatic loading of this module FILES_CMAKE # file name of a CMake file setting source list variables # (defaults to files.cmake) DEPRECATED_SINCE # marks this modules as deprecated DESCRIPTION # a description for this module ) set(_macro_multiparams SUBPROJECTS # list of CDash labels INCLUDE_DIRS # include directories: [PUBLIC|PRIVATE|INTERFACE] INTERNAL_INCLUDE_DIRS # include dirs internal to this module (DEPRECATED) DEPENDS # list of modules this module depends on: [PUBLIC|PRIVATE|INTERFACE] DEPENDS_INTERNAL # list of modules this module internally depends on (DEPRECATED) PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.): [PUBLIC|PRIVATE|INTERFACE] TARGET_DEPENDS # list of CMake targets this module should depend on ADDITIONAL_LIBS # list of addidtional private libraries linked to this module. CPP_FILES # list of cpp files H_FILES # list of header files: [PUBLIC|PRIVATE] ) set(_macro_options FORCE_STATIC # force building this module as a static library HEADERS_ONLY # this module is a headers-only library GCC_DEFAULT_VISIBILITY # do not use gcc visibility flags - all symbols will be exported NO_DEFAULT_INCLUDE_DIRS # do not add default include directories like "include" or "." NO_INIT # do not create CppMicroServices initialization code NO_FEATURE_INFO # do not create a feature info by calling add_feature_info() WARNINGS_NO_ERRORS # do not treat compiler warnings as errors EXECUTABLE # create an executable; do not use directly, use mitk_create_executable() instead C_MODULE # compile all source files as C sources CXX_MODULE # compile all source files as C++ sources ) cmake_parse_arguments(MODULE "${_macro_options}" "${_macro_params}" "${_macro_multiparams}" ${ARGN}) set(MODULE_NAME ${MODULE_UNPARSED_ARGUMENTS}) # ----------------------------------------------------------------- # Sanity checks if(NOT MODULE_NAME) if(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME) get_filename_component(MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) else() message(SEND_ERROR "The module name must not be empty") endif() endif() set(_deprecated_args INTERNAL_INCLUDE_DIRS DEPENDS_INTERNAL EXPORT_DEFINE TARGET_DEPENDS HEADERS_ONLY) foreach(_deprecated_arg ${_deprecated_args}) if(MODULE_${_deprecated_arg}) message(WARNING "The ${_deprecated_arg} argument is deprecated") endif() endforeach() set(_module_type module) set(_Module_type Module) if(MODULE_EXECUTABLE) set(_module_type executable) set(_Module_type Executable) endif() if(MITK_MODULE_NAME_REGEX_MATCH) if(NOT ${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" does not match the regular expression \"${MITK_MODULE_NAME_REGEX_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_REGEX_NOT_MATCH) if(${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_NOT_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" must not match the regular expression \"${MITK_MODULE_NAME_REGEX_NOT_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_PREFIX AND NOT MODULE_NAME MATCHES "^${MITK_MODULE_NAME_PREFIX}.*$") set(MODULE_NAME "${MITK_MODULE_NAME_PREFIX}${MODULE_NAME}") endif() if(NOT MODULE_FILES_CMAKE) set(MODULE_FILES_CMAKE files.cmake) endif() if(NOT IS_ABSOLUTE ${MODULE_FILES_CMAKE}) set(MODULE_FILES_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_FILES_CMAKE}) endif() if(NOT MODULE_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) elseif(TARGET MITK-Modules) set(MODULE_SUBPROJECTS MITK-Modules) endif() endif() # check if the subprojects exist as targets if(MODULE_SUBPROJECTS) foreach(subproject ${MODULE_SUBPROJECTS}) if(NOT TARGET ${subproject}) message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target") endif() endforeach() endif() # ----------------------------------------------------------------- # Check if module should be build set(MODULE_TARGET ${MODULE_NAME}) # assume worst case set(MODULE_IS_ENABLED 0) # first we check if we have an explicit module build list if(MITK_MODULES_TO_BUILD) list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX) if(_MOD_INDEX EQUAL -1) set(MODULE_IS_EXCLUDED 1) endif() endif() if(NOT MODULE_IS_EXCLUDED) # first of all we check for the dependencies _mitk_parse_package_args(${MODULE_PACKAGE_DEPENDS}) mitk_check_module_dependencies(MODULES ${MODULE_DEPENDS} PACKAGES ${PACKAGE_NAMES} MISSING_DEPENDENCIES_VAR _MISSING_DEP PACKAGE_DEPENDENCIES_VAR PACKAGE_NAMES) if(_MISSING_DEP) if(MODULE_NO_FEATURE_INFO) message("${_Module_type} ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") endif() set(MODULE_IS_ENABLED 0) else() set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${PACKAGE_NAMES}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("${_Module_type} ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) break() endif() endforeach() endif() endif() # ----------------------------------------------------------------- # Start creating the module if(MODULE_IS_ENABLED) # clear variables defined in files.cmake set(RESOURCE_FILES ) set(CPP_FILES ) set(H_FILES ) set(TXX_FILES ) set(DOX_FILES ) set(UI_FILES ) set(MOC_H_FILES ) set(QRC_FILES ) # clear other variables set(Q${KITNAME}_GENERATED_CPP ) set(Q${KITNAME}_GENERATED_MOC_CPP ) set(Q${KITNAME}_GENERATED_QRC_CPP ) set(Q${KITNAME}_GENERATED_UI_CPP ) # check and set-up auto-loading if(MODULE_AUTOLOAD_WITH) if(NOT TARGET "${MODULE_AUTOLOAD_WITH}") message(SEND_ERROR "The module target \"${MODULE_AUTOLOAD_WITH}\" specified as the auto-loading module for \"${MODULE_NAME}\" does not exist") endif() endif() set(_module_autoload_meta_target "${CMAKE_PROJECT_NAME}-autoload") # create a meta-target if it does not already exist if(NOT TARGET ${_module_autoload_meta_target}) add_custom_target(${_module_autoload_meta_target}) endif() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif() if(MITK_GENERATE_MODULE_DOT) message("MODULEDOTNAME ${MODULE_NAME}") foreach(dep ${MODULE_DEPENDS}) message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ") endforeach(dep) endif(MITK_GENERATE_MODULE_DOT) if (EXISTS ${MODULE_FILES_CMAKE}) include(${MODULE_FILES_CMAKE}) endif() if(MODULE_CPP_FILES) list(APPEND CPP_FILES ${MODULE_CPP_FILES}) endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src") # Preprend the "src" directory to the cpp file list set(_cpp_files ${CPP_FILES}) set(CPP_FILES ) foreach(_cpp_file ${_cpp_files}) list(APPEND CPP_FILES "src/${_cpp_file}") endforeach() endif() if(CPP_FILES OR RESOURCE_FILES OR UI_FILES OR MOC_H_FILES OR QRC_FILES) set(MODULE_HEADERS_ONLY 0) if(MODULE_C_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE C) elseif(MODULE_CXX_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE CXX) endif() else() set(MODULE_HEADERS_ONLY 1) if(MODULE_AUTOLOAD_WITH) message(SEND_ERROR "A headers only module cannot be auto-loaded") endif() endif() set(module_c_flags ) set(module_c_flags_debug ) set(module_c_flags_release ) set(module_cxx_flags ) set(module_cxx_flags_debug ) set(module_cxx_flags_release ) if(MODULE_GCC_DEFAULT_VISIBILITY OR NOT CMAKE_COMPILER_IS_GNUCXX) # We only support hidden visibility for gcc for now. Clang still has troubles with # correctly marking template declarations and explicit template instantiations as exported. # See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028 # and http://llvm.org/bugs/show_bug.cgi?id=10113 set(CMAKE_CXX_VISIBILITY_PRESET default) set(CMAKE_VISIBILITY_INLINES_HIDDEN 0) else() set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) endif() if(NOT MODULE_WARNINGS_NO_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCAndCXXCompilerFlags("/WX" module_c_flags module_cxx_flags) else() mitkFunctionCheckCAndCXXCompilerFlags(-Werror module_c_flags module_cxx_flags) # The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang # versions to "static-member-init", see # http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html # # Also, older Clang and seemingly all gcc versions do not warn if unknown # "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the # command line. This may get confusing if unrelated compiler errors happen and # the error output then additionally contains errors about unknown flags (which # is not the case if there were no compile errors). # # So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by # the compiler and if applicable, prints the specific warning as a real warning and # not as an error (although -Werror was given). mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" module_c_flags module_cxx_flags) + mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=class-memaccess" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=inconsistent-missing-override" module_c_flags module_cxx_flags) endif() endif() if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) if(NOT MODULE_HEADERS_ONLY) if(NOT MODULE_NO_INIT OR RESOURCE_FILES) find_package(CppMicroServices QUIET NO_MODULE REQUIRED) endif() if(NOT MODULE_NO_INIT) usFunctionGenerateModuleInit(CPP_FILES) endif() set(binary_res_files ) set(source_res_files ) if(RESOURCE_FILES) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/resource") set(res_dir resource) elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Resources") set(res_dir Resources) else() message(SEND_ERROR "Resources specified but ${CMAKE_CURRENT_SOURCE_DIR}/resource directory not found.") endif() foreach(res_file ${RESOURCE_FILES}) if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}/${res_file}) list(APPEND binary_res_files "${res_file}") else() list(APPEND source_res_files "${res_file}") endif() endforeach() # Add a source level dependencies on resource files usFunctionGetResourceSource(TARGET ${MODULE_TARGET} OUT CPP_FILES) endif() endif() if(MITK_USE_Qt5) if(UI_FILES) qt5_wrap_ui(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif() if(MOC_H_FILES) qt5_wrap_cpp(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) endif() if(QRC_FILES) qt5_add_resources(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif() endif() set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) mitkFunctionOrganizeSources( SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} UI ${UI_FILES} QRC ${QRC_FILES} MOC ${Q${KITNAME}_GENERATED_MOC_CPP} GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP} GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP} ) set(coverage_sources ${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES} ${TOOL_CPPS} ${TOOL_GUI_CPPS}) if(MODULE_SUBPROJECTS) set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() # --------------------------------------------------------------- # Create the actual module target if(MODULE_HEADERS_ONLY) add_library(${MODULE_TARGET} INTERFACE) else() if(MODULE_EXECUTABLE) add_executable(${MODULE_TARGET} ${MODULE_CPP_FILES} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set(_us_module_name main) else() add_library(${MODULE_TARGET} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set(_us_module_name ${MODULE_TARGET}) endif() # Apply properties to the module target. target_compile_definitions(${MODULE_TARGET} PRIVATE US_MODULE_NAME=${_us_module_name}) if(MODULE_C_MODULE) if(module_c_flags) string(REPLACE " " ";" module_c_flags "${module_c_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_c_flags}) endif() if(module_c_flags_debug) string(REPLACE " " ";" module_c_flags_debug "${module_c_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_debug}>) endif() if(module_c_flags_release) string(REPLACE " " ";" module_c_flags_release "${module_c_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_release}>) endif() else() if(module_cxx_flags) string(REPLACE " " ";" module_cxx_flags "${module_cxx_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_cxx_flags}) endif() if(module_cxx_flags_debug) string(REPLACE " " ";" module_cxx_flags_debug "${module_cxx_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_debug}>) endif() if(module_cxx_flags_release) string(REPLACE " " ";" module_cxx_flags_release "${module_cxx_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_release}>) endif() endif() set_property(TARGET ${MODULE_TARGET} PROPERTY US_MODULE_NAME ${_us_module_name}) # Add additional library search directories to a global property which # can be evaluated by other CMake macros, e.g. our install scripts. if(MODULE_ADDITIONAL_LIBS) target_link_libraries(${MODULE_TARGET} PRIVATE ${MODULE_ADDITIONAL_LIBS}) get_property(_mitk_additional_library_search_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) foreach(_lib_filepath ${MODULE_ADDITIONAL_LIBS}) get_filename_component(_search_path "${_lib_filepath}" PATH) if(_search_path) list(APPEND _mitk_additional_library_search_paths "${_search_path}") endif() endforeach() if(_mitk_additional_library_search_paths) list(REMOVE_DUPLICATES _mitk_additional_library_search_paths) set_property(GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS ${_mitk_additional_library_search_paths}) endif() endif() # add the target name to a global property which is used in the top-level # CMakeLists.txt file to export the target set_property(GLOBAL APPEND PROPERTY MITK_MODULE_TARGETS ${MODULE_TARGET}) if(MODULE_AUTOLOAD_WITH) # for auto-loaded modules, adapt the output directory add_dependencies(${_module_autoload_meta_target} ${MODULE_TARGET}) if(WIN32) set(_module_output_prop RUNTIME_OUTPUT_DIRECTORY) else() set(_module_output_prop LIBRARY_OUTPUT_DIRECTORY) endif() set(_module_output_dir ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) get_target_property(_module_is_imported ${MODULE_AUTOLOAD_WITH} IMPORTED) if(NOT _module_is_imported) # if the auto-loading module is not imported, get its location # and put the auto-load module relative to it. get_target_property(_module_output_dir ${MODULE_AUTOLOAD_WITH} ${_module_output_prop}) set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH}) else() set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) endif() set_target_properties(${MODULE_TARGET} PROPERTIES MITK_AUTOLOAD_DIRECTORY ${MODULE_AUTOLOAD_WITH}) # add the auto-load module name as a property set_property(TARGET ${MODULE_AUTOLOAD_WITH} APPEND PROPERTY MITK_AUTOLOAD_TARGETS ${MODULE_TARGET}) endif() if(binary_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${res_dir} FILES ${binary_res_files}) endif() if(source_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir} FILES ${source_res_files}) endif() if(binary_res_files OR source_res_files) usFunctionEmbedResources(TARGET ${MODULE_TARGET}) endif() if(MODULE_DEPRECATED_SINCE) set_property(TARGET ${MODULE_TARGET} PROPERTY MITK_MODULE_DEPRECATED_SINCE ${MODULE_DEPRECATED_SINCE}) endif() # create export macros if (NOT MODULE_EXECUTABLE) set(_export_macro_name ) if(MITK_LEGACY_EXPORT_MACRO_NAME) set(_export_macro_names EXPORT_MACRO_NAME ${MODULE_EXPORT_DEFINE} NO_EXPORT_MACRO_NAME ${MODULE_NAME}_NO_EXPORT DEPRECATED_MACRO_NAME ${MODULE_NAME}_DEPRECATED NO_DEPRECATED_MACRO_NAME ${MODULE_NAME}_NO_DEPRECATED ) endif() generate_export_header(${MODULE_NAME} ${_export_macro_names} EXPORT_FILE_NAME ${MODULE_NAME}Exports.h ) endif() target_include_directories(${MODULE_TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) endif() # --------------------------------------------------------------- # Properties for both header-only and compiled modules if(MODULE_HEADERS_ONLY) set(_module_property_type INTERFACE) else() set(_module_property_type PUBLIC) endif() if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_TARGET} ${MODULE_TARGET_DEPENDS}) endif() if(MODULE_SUBPROJECTS AND NOT MODULE_HEADERS_ONLY) set_property(TARGET ${MODULE_TARGET} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_TARGET}) endforeach() endif() set(DEPENDS "${MODULE_DEPENDS}") if(NOT MODULE_NO_INIT AND NOT MODULE_HEADERS_ONLY) # Add a CppMicroServices dependency implicitly, since it is # needed for the generated "module initialization" code. set(DEPENDS "CppMicroServices;${DEPENDS}") endif() if(DEPENDS OR MODULE_PACKAGE_DEPENDS) mitk_use_modules(TARGET ${MODULE_TARGET} MODULES ${DEPENDS} PACKAGES ${MODULE_PACKAGE_DEPENDS} ) endif() if(NOT MODULE_C_MODULE) target_compile_features(${MODULE_TARGET} ${_module_property_type} ${MITK_CXX_FEATURES}) endif() # add include directories if(MODULE_INTERNAL_INCLUDE_DIRS) target_include_directories(${MODULE_TARGET} PRIVATE ${MODULE_INTERNAL_INCLUDE_DIRS}) endif() if(NOT MODULE_NO_DEFAULT_INCLUDE_DIRS) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${MODULE_TARGET} ${_module_property_type} include) else() target_include_directories(${MODULE_TARGET} ${_module_property_type} .) endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(${MODULE_TARGET} PRIVATE src) endif() endif() target_include_directories(${MODULE_TARGET} ${_module_property_type} ${MODULE_INCLUDE_DIRS}) endif() # ----------------------------------------------------------------- # Record missing dependency information if(_MISSING_DEP) if(MODULE_DESCRIPTION) set(MODULE_DESCRIPTION "${MODULE_DESCRIPTION} (missing dependencies: ${_MISSING_DEP})") else() set(MODULE_DESCRIPTION "(missing dependencies: ${_MISSING_DEP})") endif() endif() if(NOT MODULE_NO_FEATURE_INFO) add_feature_info(${MODULE_NAME} MODULE_IS_ENABLED "${MODULE_DESCRIPTION}") endif() set(MODULE_NAME ${MODULE_NAME} PARENT_SCOPE) set(MODULE_TARGET ${MODULE_TARGET} PARENT_SCOPE) set(MODULE_IS_ENABLED ${MODULE_IS_ENABLED} PARENT_SCOPE) set(MODULE_SUBPROJECTS ${MODULE_SUBPROJECTS} PARENT_SCOPE) endfunction() diff --git a/CMake/mitkFunctionCreatePlugin.cmake b/CMake/mitkFunctionCreatePlugin.cmake index acbc2bc297..1c5faf618e 100644 --- a/CMake/mitkFunctionCreatePlugin.cmake +++ b/CMake/mitkFunctionCreatePlugin.cmake @@ -1,343 +1,344 @@ #! \brief Creates a MITK CTK plugin. #! #! This function should be called from the plugins CMakeLists.txt file. #! The target name is available after the macro call as ${PLUGIN_TARGET} #! to add additional libraries in your CMakeLists.txt. Include paths and link #! libraries are set depending on the value of the Required-Plugins header #! in your manifest_headers.cmake file. #! #! This function internally calls ctkMacroBuildPlugin() and adds support #! for Qt Help files and installers. #! #! Options: #! \param TEST_PLUGIN Mark this plug-in as a testing plug-in. #! \param NO_INSTALL Don't install this plug-in. #! #! Parameters: #! #! \param EXPORT_DIRECTIVE (required) The export directive to use in the generated #! _Exports.h file. #! #! Multi-value parameters (all optional): #! #! \param EXPORTED_INCLUDE_SUFFIXES A list of sub-directories which should #! be added to the current source directory. The resulting directories #! will be available in the set of include directories of depending plug-ins. #! \param MODULE_DEPENDS (optional) A list of Modules this plug-in depends on. #! \param PACKAGE_DEPENDS (optional) A list of external packages this plug-in depends on. #! \param DOXYGEN_TAGFILES (optional) Which external tag files should be available for the plugin documentation #! \param MOC_OPTIONS (optional) Additional options to pass to the Qt MOC compiler #! \param WARNINGS_NO_ERRORS (optional) Do not handle compiler warnings as errors function(mitk_create_plugin) # options set(arg_options TEST_PLUGIN # Mark this plug-in as a testing plug-in NO_INSTALL # Don't install this plug-in NO_QHP_TRANSFORM WARNINGS_NO_ERRORS ) # single value arguments set(arg_single EXPORT_DIRECTIVE # (required) TODO: could be generated via CMake as it is done for MITK modules already ) # multiple value arguments set(arg_multiple EXPORTED_INCLUDE_SUFFIXES # (optional) additional public include directories MODULE_DEPENDS # (optional) PACKAGE_DEPENDS DOXYGEN_TAGFILES MOC_OPTIONS SUBPROJECTS ) cmake_parse_arguments(_PLUGIN "${arg_options}" "${arg_single}" "${arg_multiple}" ${ARGN}) if(_PLUGIN_TEST_PLUGIN) set(_PLUGIN_NO_INSTALL 1) set(is_test_plugin "TEST_PLUGIN") else() set(is_test_plugin) endif() set(_PLUGIN_MOC_OPTIONS "-DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED ${_PLUGIN_MOC_OPTIONS}") set(PLUGIN_TARGET ${PROJECT_NAME}) mitk_check_module_dependencies(MODULES ${_PLUGIN_MODULE_DEPENDS} PACKAGES ${_PLUGIN_PACKAGE_DEPENDS} MISSING_DEPENDENCIES_VAR _missing_deps MODULE_DEPENDENCIES_VAR _module_deps PACKAGE_DEPENDENCIES_VAR _package_deps) if(_missing_deps) if(NOT MITK_BUILD_ALL_PLUGINS) message(SEND_ERROR "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}") else() message(STATUS "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}") endif() return() endif() # -------------- All dependencies are resolved ------------------ message(STATUS "Creating CTK plugin ${PROJECT_NAME}") include(files.cmake) set(_PLUGIN_CPP_FILES ${CPP_FILES}) set(_PLUGIN_MOC_H_FILES ${MOC_H_FILES}) set(_PLUGIN_UI_FILES ${UI_FILES}) set(_PLUGIN_CACHED_RESOURCE_FILES ${CACHED_RESOURCE_FILES}) set(_PLUGIN_TRANSLATION_FILES ${TRANSLATION_FILES}) set(_PLUGIN_QRC_FILES ${QRC_FILES}) set(_PLUGIN_H_FILES ${H_FILES}) set(_PLUGIN_TXX_FILES ${TXX_FILES}) set(_PLUGIN_DOX_FILES ${DOX_FILES}) set(_PLUGIN_CMAKE_FILES ${CMAKE_FILES} files.cmake) set(_PLUGIN_FILE_DEPENDENCIES ${FILE_DEPENDENCIES}) if(CTK_PLUGINS_OUTPUT_DIR) set(_output_dir "${CTK_PLUGINS_OUTPUT_DIR}") else() set(_output_dir "") endif() # Compute the plugin dependencies ctkFunctionGetTargetLibraries(_PLUGIN_target_libraries "") #------------------------------------------------------------# #------------------ Qt Help support -------------------------# set(PLUGIN_GENERATED_QCH_FILES ) if(BLUEBERRY_USE_QT_HELP AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/documentation/UserManual") set(PLUGIN_DOXYGEN_INPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/documentation/UserManual") set(PLUGIN_DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/documentation/UserManual") # Create a list of Doxygen tag files from the plug-in dependencies set(PLUGIN_DOXYGEN_TAGFILES) foreach(_dep_target ${_PLUGIN_target_libraries}) string(REPLACE _ . _dep ${_dep_target}) get_target_property(_is_imported ${_dep_target} IMPORTED) if(_is_imported) get_target_property(_import_loc_debug ${_dep_target} IMPORTED_LOCATION_DEBUG) get_target_property(_import_loc_release ${_dep_target} IMPORTED_LOCATION_RELEASE) # There is not necessarily a debug and release build if(_import_loc_release) set(_import_loc ${_import_loc_release}) else() set(_import_loc ${_import_loc_debug}) endif() get_filename_component(_target_filename "${_import_loc}" NAME) # on windows there might be a Debug or Release subdirectory string(REGEX REPLACE "/bin/plugins/(Debug/|Release/)?${_target_filename}" "/Plugins/${_dep}/documentation/UserManual" plugin_tag_dir "${_import_loc}" ) else() set(plugin_tag_dir "${CMAKE_BINARY_DIR}/Plugins/${_dep}/documentation/UserManual") endif() set(_tag_file "${plugin_tag_dir}/${_dep_target}.tag") if(EXISTS ${_tag_file}) set(PLUGIN_DOXYGEN_TAGFILES "${PLUGIN_DOXYGEN_TAGFILES} \"${_tag_file}=qthelp://${_dep}/bundle/\"") endif() endforeach() if(_PLUGIN_DOXYGEN_TAGFILES) set(PLUGIN_DOXYGEN_TAGFILES "${PLUGIN_DOXYGEN_TAGFILES} ${_PLUGIN_DOXYGEN_TAGFILES}") endif() #message("PLUGIN_DOXYGEN_TAGFILES: ${PLUGIN_DOXYGEN_TAGFILES}") if(_PLUGIN_NO_QHP_TRANSFORM) set(_use_qhp_xsl 0) else() set(_use_qhp_xsl 1) endif() _FUNCTION_CREATE_CTK_QT_COMPRESSED_HELP(PLUGIN_GENERATED_QCH_FILES ${_use_qhp_xsl}) list(APPEND _PLUGIN_CACHED_RESOURCE_FILES ${PLUGIN_GENERATED_QCH_FILES}) endif() #------------------------------------------------------------# #------------------ Create Plug-in --------------------------# mitkFunctionOrganizeSources( SOURCE ${_PLUGIN_CPP_FILES} HEADER ${_PLUGIN_H_FILES} TXX ${_PLUGIN_TXX_FILES} DOC ${_PLUGIN_DOX_FILES} UI ${_PLUGIN_UI_FILES} QRC ${_PLUGIN_QRC_FILES} ${_PLUGIN_CACHED_RESOURCE_FILES} META ${_PLUGIN_META_FILES} MOC ${MY_MOC_CPP} GEN_UI ${MY_UI_CPP} GEN_QRC ${MY_QRC_SRCS} ) ctkMacroBuildPlugin( NAME ${PLUGIN_TARGET} EXPORT_DIRECTIVE ${_PLUGIN_EXPORT_DIRECTIVE} SRCS ${_PLUGIN_CPP_FILES} ${_PLUGIN_H_FILES} ${CORRESPONDING__H_FILES} ${GLOBBED__H_FILES} MOC_SRCS ${_PLUGIN_MOC_H_FILES} MOC_OPTIONS ${_PLUGIN_MOC_OPTIONS} UI_FORMS ${_PLUGIN_UI_FILES} EXPORTED_INCLUDE_SUFFIXES ${_PLUGIN_EXPORTED_INCLUDE_SUFFIXES} RESOURCES ${_PLUGIN_QRC_FILES} TARGET_LIBRARIES ${_PLUGIN_target_libraries} CACHED_RESOURCEFILES ${_PLUGIN_CACHED_RESOURCE_FILES} TRANSLATIONS ${_PLUGIN_TRANSLATION_FILES} OUTPUT_DIR ${_output_dir} NO_INSTALL # we install the plug-in ourselves ${is_test_plugin} ) mitk_use_modules(TARGET ${PLUGIN_TARGET} MODULES ${_PLUGIN_MODULE_DEPENDS} PACKAGES ${_PLUGIN_PACKAGE_DEPENDS} ) set_property(TARGET ${PLUGIN_TARGET} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${PLUGIN_TARGET}) set_property(TARGET ${PLUGIN_TARGET} PROPERTY US_MODULE_NAME ${PLUGIN_TARGET}) set(plugin_c_flags) set(plugin_cxx_flags) if(NOT _PLUGIN_WARNINGS_NO_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCAndCXXCompilerFlags("/WX" plugin_c_flags plugin_cxx_flags) else() mitkFunctionCheckCAndCXXCompilerFlags(-Werror plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" plugin_c_flags plugin_cxx_flags) + mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=cast-function-type" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=inconsistent-missing-override" plugin_c_flags plugin_cxx_flags) endif() endif() if(plugin_c_flags) string(REPLACE " " ";" plugin_c_flags "${plugin_c_flags}") target_compile_options(${PLUGIN_TARGET} PRIVATE ${plugin_c_flags}) endif() if(plugin_cxx_flags) string(REPLACE " " ";" plugin_cxx_flags "${plugin_cxx_flags}") target_compile_options(${PLUGIN_TARGET} PRIVATE ${plugin_cxx_flags}) endif() if(NOT MY_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MY_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) elseif(TARGET MITK-Plugins) set(MY_SUBPROJECTS MITK-Plugins) endif() endif() if(MY_SUBPROJECTS) set_property(TARGET ${PLUGIN_TARGET} PROPERTY LABELS ${MY_SUBPROJECTS}) foreach(subproject ${MY_SUBPROJECTS}) add_dependencies(${subproject} ${PLUGIN_TARGET}) endforeach() endif() if(_PLUGIN_TEST_PLUGIN) find_package(CppUnit REQUIRED) target_include_directories(${PLUGIN_TARGET} PRIVATE ${CppUnit_INCLUDE_DIRS}) target_link_libraries(${PLUGIN_TARGET} PRIVATE ${CppUnit_LIBRARIES}) endif() if(mbilog_FOUND) target_link_libraries(${PLUGIN_TARGET} PRIVATE mbilog) endif() set(_PLUGIN_META_FILES "${CMAKE_CURRENT_SOURCE_DIR}/manifest_headers.cmake") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin.xml") list(APPEND _PLUGIN_META_FILES "${CMAKE_CURRENT_SOURCE_DIR}/plugin.xml") endif() set(PLUGIN_TARGET ${PLUGIN_TARGET} PARENT_SCOPE) #------------------------------------------------------------# #------------------ Installer support -----------------------# if(NOT _PLUGIN_NO_INSTALL) set(install_directories "") if(NOT MACOSX_BUNDLE_NAMES) set(install_directories bin/plugins) else(NOT MACOSX_BUNDLE_NAMES) foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND install_directories ${bundle_name}.app/Contents/MacOS/plugins) endforeach(bundle_name) endif(NOT MACOSX_BUNDLE_NAMES) foreach(install_subdir ${install_directories}) mitkFunctionInstallCTKPlugin(TARGETS ${PLUGIN_TARGET} DESTINATION ${install_subdir}) endforeach() set(_autoload_targets ) foreach(_dependency ${_module_deps}) get_target_property(_dep_autoloads ${_dependency} MITK_AUTOLOAD_TARGETS) if (_dep_autoloads) list(APPEND _autoload_targets ${_dep_autoloads}) endif() endforeach() # The MITK_AUTOLOAD_TARGETS property is used in the mitkFunctionInstallAutoLoadModules # macro which expects a list of plug-in targets. if (_autoload_targets) list(REMOVE_DUPLICATES _autoload_targets) set_target_properties(${PLUGIN_TARGET} PROPERTIES MITK_AUTOLOAD_TARGETS "${_autoload_targets}") endif() endif() endfunction() function(_FUNCTION_CREATE_CTK_QT_COMPRESSED_HELP qch_file use_xsl) set(_manifest_path "${CMAKE_CURRENT_SOURCE_DIR}/manifest_headers.cmake") if(NOT EXISTS ${_manifest_path}) message(FATAL_ERROR "${_manifest_path} not found") endif() include(${_manifest_path}) string(REPLACE "_" "." Plugin-SymbolicName "${PLUGIN_TARGET}") configure_file(${MITK_SOURCE_DIR}/Documentation/doxygen_plugin_manual.conf.in ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf ) set(_qhp_xsl_file "${MITK_SOURCE_DIR}/Documentation/qhp_toc.xsl") set(_generated_qhp_file "${PLUGIN_DOXYGEN_OUTPUT_DIR}/html/index.qhp") set(_transformed_qhp_file "${PLUGIN_DOXYGEN_OUTPUT_DIR}/html/${PLUGIN_TARGET}.qhp") set(${qch_file} "${CMAKE_CURRENT_BINARY_DIR}/resources/${PLUGIN_TARGET}.qch") set(_xsl_command ) if(use_xsl) set(_xsl_command COMMAND ${QT_XMLPATTERNS_EXECUTABLE} ${_qhp_xsl_file} ${_generated_qhp_file} -output ${_transformed_qhp_file}) endif() file(GLOB _file_dependencies "${PLUGIN_DOXYGEN_INPUT_DIR}/*") add_custom_command(OUTPUT ${${qch_file}} # Generate a Qt help project (index.qhp) with doxygen COMMAND ${DOXYGEN_EXECUTABLE} ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf # Use a XSL transformation to get rid of the top-level entry ${_xsl_command} # Generate the final Qt compressed help file (.qch) COMMAND ${QT_HELPGENERATOR_EXECUTABLE} ${_transformed_qhp_file} -o ${${qch_file}} DEPENDS ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf ${_file_dependencies} ) #set_source_files_properties(${qch_file} PROPERTIES GENERATED 1) set(${qch_file} ${${qch_file}} PARENT_SCOPE) endfunction() function(MACRO_CREATE_MITK_CTK_PLUGIN) message(SEND_ERROR "The function MACRO_CREATE_MITK_CTK_PLUGIN was renamed to mitk_create_plugin in MITK 2015.05.") endfunction() diff --git a/CMake/mitkTestPluginGenerator.cmake b/CMake/mitkTestPluginGenerator.cmake index 753f8a5689..cf63eeefe3 100644 --- a/CMake/mitkTestPluginGenerator.cmake +++ b/CMake/mitkTestPluginGenerator.cmake @@ -1,113 +1,113 @@ if(BUILD_TESTING) set(proj GP) # Means GenerateProject (use a short name due to Windows limitations) set(test_project_out_dir "${MITK_BINARY_DIR}") set(test_project_source_dir "${MITK_BINARY_DIR}/${proj}") set(test_project_binary_dir "${MITK_BINARY_DIR}/${proj}-bin") add_test(NAME mitkPluginGeneratorCleanTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_source_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest2 COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_binary_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest2 PROPERTIES LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest3 COMMAND ${CMAKE_COMMAND} -E make_directory "${test_project_binary_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest3 PROPERTIES DEPENDS mitkPluginGeneratorCleanTest2 LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCreateTest COMMAND ${exec_target} --project-name "${proj}" --project-app-name "TestApp" -ps org.test.plugin -pn "Test Plugin" -vn "Test View" - -o ${test_project_out_dir} -y -n + -o ${test_project_out_dir} -y ) set_tests_properties(mitkPluginGeneratorCreateTest PROPERTIES DEPENDS "${exec_target};mitkPluginGeneratorCleanTest;mitkPluginGeneratorCleanTest3" LABELS "MITK;BlueBerry") set(configure_options -DMITK_DIR:PATH=${MITK_BINARY_DIR} -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} -G${CMAKE_GENERATOR} -C "${MITK_BINARY_DIR}/mitkTestInitialCache.txt" ) if(CMAKE_PREFIX_PATH) string (REPLACE ";" "$" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") list(APPEND configure_options -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}) endif() if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) add_test(NAME mitkPluginGeneratorConfigureTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${config} PROPERTIES DEPENDS mitkPluginGeneratorCreateTest LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorBuildTest-${config} CONFIGURATIONS ${config} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${config}) set_tests_properties(mitkPluginGeneratorBuildTest-${config} PROPERTIES DEPENDS mitkPluginGeneratorConfigureTest-${config} LABELS "MITK;BlueBerry") endforeach() else() add_test(NAME mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS mitkPluginGeneratorCreateTest LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${CMAKE_BUILD_TYPE}) set_tests_properties(mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} LABELS "MITK;BlueBerry") endif() set(package_test_configurations) if(WIN32) # Only test packaging if build type is "Release" on Windows set(package_test_configurations CONFIGURATIONS Release) endif() if(NOT MITK_FAST_TESTING) if(WIN32) # Only test packaging if build type is "Release" on Windows add_test(NAME mitkPluginGeneratorPackageTest CONFIGURATIONS Release COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config Release --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-Release TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") elseif(CMAKE_BUILD_TYPE) add_test(mitkPluginGeneratorPackageTest ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config ${CMAKE_BUILD_TYPE} --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} TIMEOUT 6000 LABELS "MITK;BlueBerry;PACKAGE_TESTS") endif() endif() endif() diff --git a/CMakeExternals/ITK-VNL-2018-05-16.patch b/CMakeExternals/ITK-VNL-2018-05-16.patch new file mode 100644 index 0000000000..78bff5c404 --- /dev/null +++ b/CMakeExternals/ITK-VNL-2018-05-16.patch @@ -0,0 +1,2048 @@ +diff --git a/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt +index 2b85b7bc79..4c66ee43b4 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt +@@ -12,26 +12,51 @@ + # Root vxl + # + # vxl-maintainers@lists.sf.net +-cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR) +- +-# Set policies for cmake +-if( POLICY CMP0003 ) +- cmake_policy(SET CMP0003 NEW) +-endif() +-# Use @rpath on OS X +-if( POLICY CMP0042 ) +- cmake_policy(SET CMP0042 NEW) ++if( "${CMAKE_CXX_STANDARD}" MATCHES "(11|14|17|20)") ++ # If building for modern C++ language standards, ++ # require use of newer cmake version ++ cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR) ++else() ++ cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) + endif() ++# Set policies consistent with newer versions of cmake ++# to ease integration with projects that require newer ++# cmake versions. ++ ++foreach(p ++ ## Only policies introduced after the cmake_minimum_required ++ ## version need to explicitly be set to NEW. ++ ++ ##----- Policies Introduced by CMake 3.10ΒΆ ++ CMP0071 #: Let AUTOMOC and AUTOUIC process GENERATED files. ++ CMP0070 #: Define file(GENERATE) behavior for relative paths. ++ ##----- Policies Introduced by CMake 3.9 ++ CMP0069 #: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. ++ CMP0068 #: RPATH settings on macOS do not affect install_name. ++ ##----- Policies Introduced by CMake 3.8 ++ CMP0067 #: Honor language standard in try_compile() source-file signature. ++ ##----- Policies Introduced by CMake 3.7 ++ CMP0066 #: Honor per-config flags in try_compile() source-file signature. ++ ##----- Policies Introduced by CMake 3.4 ++ CMP0065 #: Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property. ++ CMP0064 #: Support new TEST if() operator. ++ ) ++ if(POLICY ${p}) ++ cmake_policy(SET ${p} NEW) ++ endif() ++endforeach() + +-# Honor visibility properties for static libraries +-if( POLICY CMP0063 ) +- cmake_policy(SET CMP0063 NEW) +-endif() + + project(vxl) + + include(CMakeDependentOption) + ++#Disable overzealous compiler warning. If the definition is truely missing a link error will be created. ++include(CheckCXXCompilerFlag) ++CHECK_CXX_COMPILER_FLAG(-Wno-undefined-var-template HAS_NO_UNDEFINED_VAR_TEMPLATE) ++if( HAS_NO_UNDEFINED_VAR_TEMPLATE ) ++ add_definitions( -Wno-undefined-var-template ) ++endif() + + find_program( MEMORYCHECK_COMMAND valgrind ) + if(MEMORYCHECK_COMMAND) +@@ -113,6 +138,7 @@ option(VXL_LEGACY_ERROR_REPORTING "Use old error reporting methods rather than e + if(VXL_LEGACY_ERROR_REPORTING) + add_definitions( -DVXL_LEGACY_ERROR_REPORTING ) + endif() ++option(VXL_RUN_FAILING_TESTS "Enable long-time failing tests. If tests are failing for a long time, turn them off by default." OFF) + + # Option to build Windows Unicode support, the string + # type of which is wchar_t, each character is a 16-bit unsigned integer. +@@ -232,7 +258,7 @@ add_subdirectory(core) + + # Optionally build the contributed libraries + if( EXISTS ${CMAKE_CURRENT_LIST_DIR}/contrib/CMakeLists.txt ) +- CMAKE_DEPENDENT_OPTION(BUILD_CONTRIB "Build the contributed libraries?" ON "BUILD_CORE_GEOMETRY;BUILD_CORE_NUMERICS;BUILD_CORE_UTILITIES;BUILD_CORE_SERIALISATION;BUILD_CORE_IMAGING" OFF) ++ CMAKE_DEPENDENT_OPTION(BUILD_CONTRIB "Build the contributed libraries?" OFF "BUILD_CORE_GEOMETRY;BUILD_CORE_NUMERICS;BUILD_CORE_UTILITIES;BUILD_CORE_SERIALISATION;BUILD_CORE_IMAGING" OFF) + add_subdirectory(contrib) + endif() + +diff --git a/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake b/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake +deleted file mode 100644 +index f2620f7bf6..0000000000 +--- a/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake ++++ /dev/null +@@ -1,8 +0,0 @@ +-# CTest Configuration for VXL +-set(CTEST_PROJECT_NAME "VXL") +-set(CTEST_NIGHTLY_START_TIME "22:00:00 EST") +- +-set(CTEST_DROP_METHOD "http") +-set(CTEST_DROP_SITE "open.cdash.org") +-set(CTEST_DROP_LOCATION "/submit.php?project=vxl") +-set(CTEST_DROP_SITE_CDASH TRUE) +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake +new file mode 100644 +index 0000000000..ad941254ff +--- /dev/null ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake +@@ -0,0 +1,41 @@ ++# ++# Find a CLIPPER library ++# ++# This file is used to manage using either a natively provided CLIPPER library or the one in v3p if provided. ++# ++# ++# As per the standard scheme the following definitions are used ++# CLIPPER_INCLUDE_DIR - where to find clipper.hxx ++# CLIPPER_LIBRARIES - the set of libraries to include to use CLIPPER. ++# CLIPPER_FOUND - TRUE, if available somewhere on the system. ++ ++# Additionally ++# VXL_USING_NATIVE_CLIPPER - True if we are using a CLIPPER library provided outside vxl (or v3p) ++ ++if( NOT CLIPPER_FOUND ) ++ ++ # If this FORCE variable is unset or is FALSE, try to find a native library. ++ if( NOT VXL_FORCE_V3P_CLIPPER ) ++ # ./FindGEOTIFF.cmake does this instead... ++ #include( ${MODULE_PATH}/NewCMake/FindGEOTIFF.cmake ) ++ find_package( CLIPPER QUIET ) ++ if( CLIPPER_FOUND ) ++ set(VXL_USING_NATIVE_CLIPPER "YES") ++ endif() ++ endif() ++ ++ # ++ # At some point, in a "release" version, it is possible that someone ++ # will not have the v3p clipper library, so make sure the headers ++ # exist. ++ # ++ if( NOT CLIPPER_FOUND ) ++ if(EXISTS ${VXL_ROOT_SOURCE_DIR}/v3p/clipper/clipper.h) ++ set( CLIPPER_FOUND "YES" ) ++ set( CLIPPER_INCLUDE_DIR ${clipper_BINARY_DIR} ${clipper_SOURCE_DIR}) ++ set( CLIPPER_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_DIR}/include/vxl/v3p/clipper) ++ set( CLIPPER_LIBRARIES clipper ) ++ endif() ++ endif() ++ ++endif() +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake +index 69e9ea9371..9ba8283a63 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake +@@ -69,9 +69,11 @@ if(APPLE) + endif() + + if(UNIX) +- find_path( OPENCL_INCLUDE_PATH CL/cl_gl.h PATHS /usr/include /usr/include/nvidia-current /usr/local/cuda/include) +- find_path(OPENCL_LIBRARY_PATH libOpenCL.so PATHS /usr/lib /usr/lib/nvidia-current /usr/local/cuda/lib64 ${OPENCL_LIBRARY_PATH} ) +- find_library(OPENCL_LIBRARIES NAMES libOpenCL.so PATHS /usr/lib /usr/lib/nvidia-current ${OPENCL_LIBRARY_PATH} ) ++ file(GLOB AMD_DIR /opt/AMDAPPSDK-*/include) ++ find_path( OPENCL_INCLUDE_PATH CL/cl_gl.h PATHS /usr/include /usr/include/nvidia-current /usr/local/cuda/include HINTS ${AMD_DIR}) ++ file(GLOB AMD_DIR /opt/AMDAPPSDK-*/lib/x86_64/sdk /opt/AMDAPPSDK-*/lib/x86_64) ++ find_path(OPENCL_LIBRARY_PATH libOpenCL.so PATHS /usr/lib /usr/lib64 /usr/lib/nvidia-current /usr/local/cuda/lib64 ${OPENCL_LIBRARY_PATH} HINTS ${AMD_DIR} ) ++ find_library(OPENCL_LIBRARIES NAMES libOpenCL.so PATHS /usr/lib /usr/lib64 /usr/lib/nvidia-current ${OPENCL_LIBRARY_PATH} ) + if(OPENCL_INCLUDE_PATH) + if(OPENCL_LIBRARIES) + set(OPENCL_FOUND "YES") +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt +index b69c359257..9387e9b15c 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt +@@ -5,9 +5,9 @@ To facilitate the deprecation of modules, place code similar to the + following in the FindXXX.cmake as soon as it becomes part of a CMake + release: + +-# FIXME: When cmake_minimum_version reaches 2.6.2 the FindXXX ++# FIXME: When cmake_minimum_version reaches 3.3.0 the FindXXX + # module in this directory is not needed anymore. +-IF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 2.6.1) ++IF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 3.3.0) + MESSAGE(FATAL_ERROR + "FindXXX not needed in vxl; it is now available in CMake.") +-ENDIF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 2.6.1) ++ENDIF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 3.3.0) +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake +index b0d7dd49cd..ad54658342 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake +@@ -1,13 +1,5 @@ +-# This version of GenerateExportHeader extends CMake's version to provide the +-# _TEMPLATE_EXPORT macro. For templated class declarations, Windows +-# must not have the export specification, while GCC must have the export +-# specification. +-# +-# This macro is for templates with explicit instantiations built into a library. +-# +-# To avoid inadvertently overriding CMake's or another package's +-# GenerateExportHeader, this version is named differently and adds a prefix to +-# all global identifiers. ++# Distributed under the OSI-approved BSD 3-Clause License. See accompanying ++# file Copyright.txt or https://cmake.org/licensing for details. + + #.rst: + # VXLGenerateExportHeader +@@ -28,10 +20,12 @@ + # [EXPORT_FILE_NAME ] + # [DEPRECATED_MACRO_NAME ] + # [NO_EXPORT_MACRO_NAME ] ++# [INCLUDE_GUARD_NAME ] + # [STATIC_DEFINE ] + # [NO_DEPRECATED_MACRO_NAME ] + # [DEFINE_NO_DEPRECATED] + # [PREFIX_NAME ] ++# [CUSTOM_CONTENT_FROM_VARIABLE ] + # ) + # + # +@@ -71,9 +65,10 @@ + # + # The CMake fragment will generate a file in the + # ``${CMAKE_CURRENT_BINARY_DIR}`` called ``somelib_export.h`` containing the +-# macros ``SOMELIB_EXPORT``, ``SOMELIB_TEMPLATE_EXPORT``, ``SOMELIB_NO_EXPORT``, +-# ``SOMELIB_DEPRECATED``, ``SOMELIB_DEPRECATED_EXPORT`` and +-# ``SOMELIB_DEPRECATED_NO_EXPORT``. ++# macros ``SOMELIB_EXPORT``, ``SOMELIB_NO_EXPORT``, ``SOMELIB_DEPRECATED``, ++# ``SOMELIB_DEPRECATED_EXPORT`` and ``SOMELIB_DEPRECATED_NO_EXPORT``. ++# They will be followed by content taken from the variable specified by ++# the ``CUSTOM_CONTENT_FROM_VARIABLE`` option, if any. + # The resulting file should be installed with other headers in the library. + # + # The ``BASE_NAME`` argument can be used to override the file name and the +@@ -91,7 +86,7 @@ + # ``OTHER_NAME_EXPORT``, ``OTHER_NAME_NO_EXPORT`` and ``OTHER_NAME_DEPRECATED`` + # etc. + # +-# The ``BASE_NAME`` may be overridden by specifiying other options in the ++# The ``BASE_NAME`` may be overridden by specifying other options in the + # function. For example: + # + # .. code-block:: cmake +@@ -191,19 +186,6 @@ + # :prop_tgt:`CXX_VISIBILITY_PRESET <_VISIBILITY_PRESET>` and + # :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead. + +-#============================================================================= +-# Copyright 2011 Stephen Kelly +-# +-# Distributed under the OSI-approved BSD License (the "License"); +-# see accompanying file Copyright.txt for details. +-# +-# This software is distributed WITHOUT ANY WARRANTY; without even the +-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +-# See the License for more information. +-#============================================================================= +-# (To distribute this file outside of CMake, substitute the full +-# License text for the above reference.) +- + include(CMakeParseArguments) + include(CheckCXXCompilerFlag) + +@@ -218,7 +200,7 @@ macro(_vxl_test_compiler_hidden_visibility) + + if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2") + set(GCC_TOO_OLD TRUE) +- elseif(CMAKE_COMPILER_IS_GNUC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") ++ elseif(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") + set(GCC_TOO_OLD TRUE) + elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0") + set(_INTEL_TOO_OLD TRUE) +@@ -236,14 +218,15 @@ macro(_vxl_test_compiler_hidden_visibility) + check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) + check_cxx_compiler_flag(-fvisibility-inlines-hidden + COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) +- option(USE_COMPILER_HIDDEN_VISIBILITY +- "Use HIDDEN visibility support if available." ON) +- mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) + endif() + endmacro() + + macro(_vxl_test_compiler_has_deprecated) ++ # NOTE: Some Embarcadero compilers silently compile __declspec(deprecated) ++ # without error, but this is not a documented feature and the attribute does ++ # not actually generate any warnings. + if(CMAKE_CXX_COMPILER_ID MATCHES Borland ++ OR CMAKE_CXX_COMPILER_ID MATCHES Embarcadero + OR CMAKE_CXX_COMPILER_ID MATCHES HP + OR GCC_TOO_OLD + OR CMAKE_CXX_COMPILER_ID MATCHES PGI +@@ -270,8 +253,6 @@ macro(_VXL_DO_SET_MACRO_VALUES TARGET_LIBRARY) + set(DEFINE_DEPRECATED) + set(DEFINE_EXPORT) + set(DEFINE_IMPORT) +- set(DEFINE_TEMPLATE_EXPORT) +- set(DEFINE_TEMPLATE_IMPORT) + set(DEFINE_NO_EXPORT) + + if (COMPILER_HAS_DEPRECATED_ATTR) +@@ -288,12 +269,12 @@ macro(_VXL_DO_SET_MACRO_VALUES TARGET_LIBRARY) + set(DEFINE_IMPORT "__declspec(dllimport)") + set(DEFINE_TEMPLATE_EXPORT) + set(DEFINE_TEMPLATE_IMPORT) +- elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) ++ elseif(COMPILER_HAS_HIDDEN_VISIBILITY) + set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") + set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") ++ set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") + set(DEFINE_TEMPLATE_EXPORT "${DEFINE_EXPORT}") + set(DEFINE_TEMPLATE_IMPORT "${DEFINE_IMPORT}") +- set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") + endif() + endif() + endmacro() +@@ -301,10 +282,10 @@ endmacro() + macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) + # Option overrides + set(options DEFINE_NO_DEPRECATED) +- set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME +- TEMPLATE_EXPORT_MACRO_NAME EXPORT_FILE_NAME ++ set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME ++ TEMPLATE_EXPORT_MACRO_NAME + DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE +- NO_DEPRECATED_MACRO_NAME) ++ NO_DEPRECATED_MACRO_NAME CUSTOM_CONTENT_FROM_VARIABLE INCLUDE_GUARD_NAME) + set(multiValueArgs) + + cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" +@@ -339,9 +320,7 @@ macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) + if(_GEH_TEMPLATE_EXPORT_MACRO_NAME) + set(TEMPLATE_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_TEMPLATE_EXPORT_MACRO_NAME}) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) +- endif() ++ string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) + if(_GEH_EXPORT_FILE_NAME) + if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) + set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) +@@ -352,43 +331,47 @@ macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) + if(_GEH_DEPRECATED_MACRO_NAME) + set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) +- endif() ++ string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) + if(_GEH_NO_EXPORT_MACRO_NAME) + set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) +- endif() ++ string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) + if(_GEH_STATIC_DEFINE) + set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) +- endif() ++ string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) + + if(_GEH_DEFINE_NO_DEPRECATED) +- set(DEFINE_NO_DEPRECATED TRUE) ++ set(DEFINE_NO_DEPRECATED 1) ++ else() ++ set(DEFINE_NO_DEPRECATED 0) + endif() + + if(_GEH_NO_DEPRECATED_MACRO_NAME) + set(NO_DEPRECATED_MACRO_NAME + ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) +- endif() ++ string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) + +- set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") ++ if(_GEH_INCLUDE_GUARD_NAME) ++ set(INCLUDE_GUARD_NAME ${_GEH_INCLUDE_GUARD_NAME}) ++ else() ++ set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") ++ endif() + + get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) + + if(NOT EXPORT_IMPORT_CONDITION) + set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) + endif() +- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) +- string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) ++ string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) ++ ++ if(_GEH_CUSTOM_CONTENT_FROM_VARIABLE) ++ if(DEFINED "${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}") ++ set(CUSTOM_CONTENT "${${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}}") ++ else() ++ set(CUSTOM_CONTENT "") ++ endif() + endif() + + configure_file("${_VXL_GENERATE_EXPORT_HEADER_MODULE_DIR}/vxlexportheader.cmake.in" +@@ -418,6 +401,9 @@ function(vxl_add_compiler_export_flags) + _vxl_test_compiler_hidden_visibility() + _vxl_test_compiler_has_deprecated() + ++ option(USE_COMPILER_HIDDEN_VISIBILITY ++ "Use HIDDEN visibility support if available." ON) ++ mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) + if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) + # Just return if there are no flags to add. + return() +@@ -434,6 +420,7 @@ function(vxl_add_compiler_export_flags) + if(ARGC GREATER 0) + set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) + else() +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) ++ string(APPEND CMAKE_CXX_FLAGS " ${EXTRA_FLAGS}") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) + endif() + endfunction() +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake +index a921edcf51..1d1ebc6e72 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake +@@ -752,11 +752,10 @@ if(NOT VCL_CXX_HAS_HEADER_LIMITS) + message(FATAL_ERROR "Compiler is required to have limits.h") + else() + PERFORM_CMAKE_TEST_RUN(${VXL_PLFM_TEST_FILE} VCL_NUMERIC_LIMITS_HAS_INFINITY) +- # ITK does not require has_infinity +- #if(NOT VCL_NUMERIC_LIMITS_HAS_INFINITY) +- #message(FATAL_ERROR "Compiler is required to have has_infinity.") +- #endif() +- #unset(VCL_NUMERIC_LIMITS_HAS_INFINITY) ++ if(NOT VCL_NUMERIC_LIMITS_HAS_INFINITY) ++ message(FATAL_ERROR "Compiler is required to have has_infinity.") ++ endif() ++ unset(VCL_NUMERIC_LIMITS_HAS_INFINITY) + endif() + unset(VCL_CXX_HAS_HEADER_LIMITS) + +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt +index 7b6e95b121..f2133fdffd 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt +@@ -1,12 +1,32 @@ + # vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt + # +-cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR) +-if(POLICY CMP0025) +- cmake_policy(SET CMP0025 NEW) +-endif() +-if(POLICY CMP0042) +- cmake_policy(SET CMP0042 NEW) +-endif() ++cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) ++# Set policies consistent with newer versions of cmake ++# to ease integration with projects that require newer ++# cmake versions. ++ ++foreach(p ++ ## Only policies introduced after the cmake_minimum_required ++ ## version need to explicitly be set to NEW. ++ ++ ##----- Policies Introduced by CMake 3.10ΒΆ ++ CMP0071 #: Let AUTOMOC and AUTOUIC process GENERATED files. ++ CMP0070 #: Define file(GENERATE) behavior for relative paths. ++ ##----- Policies Introduced by CMake 3.9 ++ CMP0069 #: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. ++ CMP0068 #: RPATH settings on macOS do not affect install_name. ++ ##----- Policies Introduced by CMake 3.8 ++ CMP0067 #: Honor language standard in try_compile() source-file signature. ++ ##----- Policies Introduced by CMake 3.7 ++ CMP0066 #: Honor per-config flags in try_compile() source-file signature. ++ ##----- Policies Introduced by CMake 3.4 ++ CMP0065 #: Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property. ++ CMP0064 #: Support new TEST if() operator. ++ ) ++ if(POLICY ${p}) ++ cmake_policy(SET ${p} NEW) ++ endif() ++endforeach() + project(vxl_pic_compatible) + + add_library(cmTryCompileStaticLib STATIC static_src.cxx) +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake +index 3ae1f1c166..6222df72fe 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake +@@ -112,27 +112,21 @@ macro( vxl_add_library ) + if("${VXL_INSTALL_INCLUDE_DIR}" STREQUAL "include/vxl") + ## Identify the relative path for installing the header files and txx files + string(REPLACE ${VXL_ROOT_SOURCE_DIR} "${VXL_INSTALL_INCLUDE_DIR}" relative_install_path ${CMAKE_CURRENT_SOURCE_DIR}) +- ## Added in 2.8.11 http://stackoverflow.com/questions/19460707/how-to-set-include-directories-from-a-cmakelists-txt-file +- if(${CMAKE_VERSION} VERSION_GREATER 2.8.11.2) +- target_include_directories(${lib_name} +- PUBLIC +- $ +- $ +- ) +- endif() ++ target_include_directories(${lib_name} ++ PUBLIC ++ $ ++ $ ++ ) + else() + set(relative_install_path "${VXL_INSTALL_INCLUDE_DIR}") + if(DEFINED header_install_dir) + set(relative_install_path "${relative_install_path}/${header_install_dir}") + endif() +- ## Added in 2.8.11 http://stackoverflow.com/questions/19460707/how-to-set-include-directories-from-a-cmakelists-txt-file +- if(${CMAKE_VERSION} VERSION_GREATER 2.8.11.2) +- target_include_directories(${lib_name} +- PUBLIC +- $ +- $ +- ) +- endif() ++ target_include_directories(${lib_name} ++ PUBLIC ++ $ ++ $ ++ ) + endif() + INSTALL_NOBASE_HEADER_FILES(${relative_install_path} ${lib_srcs}) + endif() +@@ -181,23 +175,14 @@ macro(SET_VXL_LIBRARY_PROPERTIES) + message(FATAL_ERROR "INSTALL_DIR REQUIRED when using USE_HIDDEN_VISIBILITY") + endif() + +- if (BUILD_SHARED_LIBS OR (APPLE AND NOT BUILD_SHARED_LIBS)) ++ if (BUILD_SHARED_LIBS OR (APPLE AND NOT BUILD_SHARED_LIBS) ) #APPLE Respects hidden visibility for static builds + # export flags are only added when building shared libs, they cause + # mismatched visibility warnings when building statically. +- if(CMAKE_VERSION VERSION_LESS 2.8.12) +- # future DEPRECATION notice from cmake: +- # "The add_compiler_export_flags function is obsolete. +- # Use the CXX_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN +- # target properties instead." +- add_compiler_export_flags(my_abi_flags) +- set_property(TARGET ${LSLHVP_TARGET_NAME} APPEND PROPERTY COMPILE_FLAGS "${my_abi_flags}") +- else() +- if (USE_COMPILER_HIDDEN_VISIBILITY) +- # Prefer to use target properties supported by newer cmake +- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) +- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES C_VISIBILITY_PRESET hidden) +- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES VISIBILITY_INLINES_HIDDEN 1) +- endif() ++ if (USE_COMPILER_HIDDEN_VISIBILITY) ++ # Prefer to use target properties supported by newer cmake ++ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) ++ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES C_VISIBILITY_PRESET hidden) ++ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES VISIBILITY_INLINES_HIDDEN 1) + endif() + endif() + endif() +diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake +index b2e8c964a9..e0142c79ca 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake ++++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake +@@ -22,11 +22,7 @@ set(VXL_CMAKE_DOXYGEN_DIR ${VXL_ROOT_SOURCE_DIR}/config/cmake/doxygen) + get_property(VXLTargets_MODULES GLOBAL PROPERTY VXLTargets_MODULES) + + set(VXL_CONFIG_CMAKE_DIR "share/vxl/cmake") +-if(${CMAKE_VERSION} VERSION_LESS 2.8.12) +- set(INTERFACE_LINK_OPTION "") +-else() +- set(INTERFACE_LINK_OPTION "EXPORT_LINK_INTERFACE_LIBRARIES") +-endif() ++set(INTERFACE_LINK_OPTION "EXPORT_LINK_INTERFACE_LIBRARIES") + + if(VXLTargets_MODULES) + export(TARGETS +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt +index 78a984911b..b6af7c2591 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt +@@ -9,12 +9,6 @@ doxygen_add_package(core-L2 "Level-2 Vision Libraries") + doxygen_add_package(core-L2E "Level-2 Vision Libraries (Experimental)") + doxygen_add_package(core-test "Test Framework") + +-# +-# Do platform-specific configuration. +-# configure files +-# +-vxl_configure_file(${CMAKE_CURRENT_LIST_DIR}/vxl_config.h.in ${PROJECT_BINARY_DIR}/vxl_config.h ${VXL_INSTALL_INCLUDE_DIR}) +-include_directories(${PROJECT_BINARY_DIR}) + + set(global_sources + vxl_copyright.h +@@ -28,6 +22,13 @@ else() + endif() + INSTALL_NOBASE_HEADER_FILES(${prefix} ${global_sources}) + ++# ++# Do platform-specific configuration. ++# configure files ++# ++vxl_configure_file(${CMAKE_CURRENT_LIST_DIR}/vxl_config.h.in ${PROJECT_BINARY_DIR}/vxl_config.h ${prefix}) ++include_directories(${PROJECT_BINARY_DIR}) ++ + if(BUILD_CORE_UTILITIES) + # POSIX layer + add_subdirectory(vpl) +@@ -122,7 +123,7 @@ endif() + + + # video +-CMAKE_DEPENDENT_OPTION (BUILD_CORE_VIDEO "Build VXL's core video libraries" ON ++CMAKE_DEPENDENT_OPTION (BUILD_CORE_VIDEO "Build VXL's core video libraries" OFF + "BUILD_CORE_UTILITIES;BUILD_CORE_IMAGING" OFF) + if (BUILD_CORE_VIDEO) + add_subdirectory(vidl) +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt +index a48b5640bf..59231aa70f 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt +@@ -24,6 +24,10 @@ option(VNL_CONFIG_THREAD_SAFE + option(VNL_CONFIG_ENABLE_SSE2 + "Enable Streaming SIMD Extensions 2 optimisations (hardware dependant). Currently broken. For use by VNL developers only." OFF) + #endif() ++if(VNL_CONFIG_ENABLE_SSE2) ++ # Tested on ubuntu and Mac. ctest becomes unstable and failures change between runs. ++ message(FATAL_ERROR "VNL_CONFIG_ENABLE_SSE2 option currently fails testing on all platforms, this is not suitable for use at the momemnt.") ++endif() + + option(VNL_CONFIG_ENABLE_SSE2_ROUNDING + "Enable Streaming SIMD Extensions 2 implementation of rounding (hardware dependant)." +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx +index 71e6e80d0a..1f14291ed6 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx +@@ -63,7 +63,6 @@ void test_convolve() + + TEST_NEAR("vnl_convolve() with_fft(16384)", (r9-r10).two_norm(), 0.0, 1e-6); + std::cout << "Done FFT-2-based 10000x2000 convolution in " << ms2/double(ntimes) << " milliseconds\n"; +- TEST("vnl_convolve() timing: should be at least 2.5x faster", 5*ms2 < 2*ms1, true); + + vnl_vector r11; + const std::clock_t timer_05 = std::clock(); +@@ -73,7 +72,6 @@ void test_convolve() + const int ms3 = ( timer_06 - timer_05)/ (CLOCKS_PER_SEC/1000); + TEST_NEAR("vnl_convolve() with_fft(12800)", (r9-r11).two_norm(), 0.0, 1e-6); + std::cout << "Done FFT-2,5-based 10000x2000 convolution in " << ms3/double(ntimes) << " milliseconds\n"; +- TEST("vnl_convolve() timing: should even be faster", 2*ms3 < 3*ms2, true); + + vnl_vector r12; + const std::clock_t timer_07 = std::clock(); +@@ -83,7 +81,6 @@ void test_convolve() + const int ms4 = ( timer_08 - timer_07)/ (CLOCKS_PER_SEC/1000); + TEST_NEAR("vnl_convolve() with_fft(27648)", (r9-r12).two_norm(), 0.0, 1e-6); + std::cout << "Done FFT-2,3-based 10000x2000 convolution in " << ms4/double(ntimes) << " milliseconds\n"; +- TEST("vnl_convolve() timing: should be slower", 5*ms4 > 3*ms2, true); + + double c1_data[] = { -1, 0, 1, 2, 3, 4 }; + vnl_vector c1(6, 6, c1_data); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx +index 89eb069622..c1c99263ae 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx +@@ -23,7 +23,7 @@ double vnl_brent::minimize_given_bounds(double ax, double bx, double cx, + double tol, + double *xmin) + { +- assert( xmin != NULL ); ++ assert( xmin != VXL_NULLPTR ); + this->set_x_tolerance( tol ); + *xmin = vnl_brent_minimizer::minimize_given_bounds( ax, bx, cx ); + return vnl_brent_minimizer::f_at_last_minimum(); +@@ -33,7 +33,7 @@ double vnl_brent::minimize_given_bounds_and_1st_f(double ax, double bx, + double fb, double cx, + double tol, double *xmin) + { +- assert( xmin != NULL ); ++ assert( xmin != VXL_NULLPTR ); + this->set_x_tolerance( tol ); + *xmin = vnl_brent_minimizer::minimize_given_bounds_and_one_f( ax, bx, cx, fb ); + return vnl_brent_minimizer::f_at_last_minimum(); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx +index 24f9607238..214d4957a5 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx +@@ -30,10 +30,10 @@ bool vnl_generalized_schur(vnl_matrix > *A, + assert(B->rows() == B->cols()); + + long n = A->rows(); +- assert(alpha!=0); alpha->set_size(n); alpha->fill(0); +- assert(beta!=0); beta ->set_size(n); beta ->fill(0); +- assert(L!=0); L ->set_size(n, n); L ->fill(0); +- assert(R!=0); R ->set_size(n, n); R ->fill(0); ++ assert(alpha!=VXL_NULLPTR); alpha->set_size(n); alpha->fill(0); ++ assert(beta!=VXL_NULLPTR); beta ->set_size(n); beta ->fill(0); ++ assert(L!=VXL_NULLPTR); L ->set_size(n, n); L ->fill(0); ++ assert(R!=VXL_NULLPTR); R ->set_size(n, n); R ->fill(0); + + long sdim = 0; + long lwork = 1000 + (8*n + 16); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx +index 3c5f3f0895..a92377cf5c 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx +@@ -47,7 +47,7 @@ vnl_vector vnl_convolve_cyclic(vnl_vector const& v1, vnl_vector const + if (n == 1) return vnl_vector(1, U(v1[0]*v2[0])); + + if (use_fft) +- return vnl_convolve_cyclic_using_fft(v1, v2, (U*)0); ++ return vnl_convolve_cyclic_using_fft(v1, v2, (U*)VXL_NULLPTR); + + vnl_vector ret(n, (U)0); // all elements already initialized to zero + for (unsigned int k=0; k vnl_convolve_using_fft(vnl_vector const& v1, vnl_vector co + vnl_vector w1(n, U(0)); for (unsigned i=0; i w2(n, U(0)); for (unsigned i=0; i(v1.size()+v2.size()-1, v1.size()+v2.size()-1, w1.data_block()); + } +@@ -98,7 +98,7 @@ vnl_vector vnl_convolve(vnl_vector const& v1, vnl_vector const& v2, int + if (v2.size() == 1) return v1*v2[0]; + + if (use_fft != 0) +- return vnl_convolve_using_fft(v1, v2, (T*)0, use_fft); ++ return vnl_convolve_using_fft(v1, v2, (T*)VXL_NULLPTR, use_fft); + + unsigned int n = v1.size() + v2.size() - 1; + vnl_vector ret(n, (T)0); // all elements already initialized to zero +@@ -120,7 +120,7 @@ vnl_vector vnl_convolve(vnl_vector const& v1, vnl_vector const& v2, U + return vnl_vector(0); + + if (use_fft != 0) +- return vnl_convolve_using_fft(v1, v2, (U*)0, use_fft); ++ return vnl_convolve_using_fft(v1, v2, (U*)VXL_NULLPTR, use_fft); + + unsigned int n = v1.size() + v2.size() - 1; + vnl_vector ret(n, (U)0); // all elements already initialized to zero +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx +index 32f784ba87..a11870bf6f 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx +@@ -9,7 +9,7 @@ + + template + vnl_fft_prime_factors::vnl_fft_prime_factors() +- : trigs_(0) ++ : trigs_(VXL_NULLPTR) + , number_(0) + { + } +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx +index 497da54958..d7d7b1960c 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx +@@ -30,11 +30,11 @@ bool vnl_generalized_schur(vnl_matrix *A, + assert(A->cols() == B->cols()); + + long n = A->rows(); +- assert(alphar!=0); alphar->set_size(n); alphar->fill(0); +- assert(alphai!=0); alphai->set_size(n); alphai->fill(0); +- assert(beta!=0); beta ->set_size(n); beta ->fill(0); +- assert(L!=0); L ->set_size(n, n); L ->fill(0); +- assert(R!=0); R ->set_size(n, n); R ->fill(0); ++ assert(alphar!=VXL_NULLPTR); alphar->set_size(n); alphar->fill(0); ++ assert(alphai!=VXL_NULLPTR); alphai->set_size(n); alphai->fill(0); ++ assert(beta!=VXL_NULLPTR); beta ->set_size(n); beta ->fill(0); ++ assert(L!=VXL_NULLPTR); L ->set_size(n, n); L ->fill(0); ++ assert(R!=VXL_NULLPTR); R ->set_size(n, n); R ->fill(0); + + long sdim = 0; + long lwork = 1000 + (8*n + 16); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx +index 9d125ea561..d1d84918bc 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx +@@ -77,7 +77,7 @@ bool vnl_lbfgs::minimize(vnl_vector& x) + std::cerr << "vnl_lbfgs: "; + + double best_f = 0; +- vnl_vector best_x = x; ++ vnl_vector best_x; + + bool ok; + this->num_evaluations_ = 0; +@@ -105,8 +105,8 @@ bool vnl_lbfgs::minimize(vnl_vector& x) + best_f = f; + } + +-#define print_(i,a,b,c,d) std::cerr<ls_ = NULL; ++ this->ls_ = VXL_NULLPTR; + } + + virtual ~lsqrVNL() +@@ -88,7 +88,7 @@ vnl_lsqr::~vnl_lsqr() + } + + // Requires number_of_residuals() of workspace in rw. +-int vnl_lsqr::aprod_(long* mode, long* m, long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata) ++int vnl_lsqr::aprod_(const long* mode, const long* m, const long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata) + { + // + // THIS CODE IS DEPRECATED +@@ -123,7 +123,7 @@ int vnl_lsqr::minimize(vnl_vector& result) + long n = ls_->get_number_of_unknowns(); + double damp = 0; + long leniw = 1; +- long* iw = 0; ++ long* iw = VXL_NULLPTR; + long lenrw = m; + #ifdef __GNUC__ + double rw[m]; +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h +index 6ab8d07f69..8ca0959993 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h +@@ -74,7 +74,7 @@ class VNL_ALGO_EXPORT vnl_lsqr + double result_norm_; + long return_code_; + +- static int aprod_(long* mode, long* m, long* n, double* x, double* y, ++ static int aprod_(const long* mode, const long* m, const long* n, double* x, double* y, + long* leniw, long* lenrw, long* iw, double* rw, + void* userdata); + }; +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h +index 56e54c1fb4..12d93958e0 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h +@@ -35,7 +35,7 @@ template + struct vnl_matrix_inverse : public vnl_svd + { + vnl_matrix_inverse(vnl_matrix const & M): vnl_svd(M) { } +- ~vnl_matrix_inverse() {} ++ ~vnl_matrix_inverse() VXL_OVERRIDE {} + + operator vnl_matrix () const { return this->inverse(); } + }; +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx +index fb19f73d27..e48bbed9f7 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx +@@ -199,10 +199,10 @@ vnl_vector vnl_qr::solve(const vnl_vector& b) const + vnl_linpack_qrsl(qrdc_out_.data_block(), + &n, &n, &p, + qraux_.data_block(), +- b_data, (T*)0, Qt_B.data_block(), ++ b_data, (T*)VXL_NULLPTR, Qt_B.data_block(), + x.data_block(), +- (T*)0/*residual*/, +- (T*)0/*Ax*/, ++ (T*)VXL_NULLPTR/*residual*/, ++ (T*)VXL_NULLPTR/*Ax*/, + &JOB, + &info); + +@@ -230,11 +230,11 @@ vnl_vector vnl_qr::QtB(const vnl_vector& b) const + &n, &n, &p, + qraux_.data_block(), + b_data, +- (T*)0, // A: Qb ++ (T*)VXL_NULLPTR, // A: Qb + Qt_B.data_block(), // B: Q'b +- (T*)0, // C: x +- (T*)0, // D: residual +- (T*)0, // E: Ax ++ (T*)VXL_NULLPTR, // C: x ++ (T*)VXL_NULLPTR, // D: residual ++ (T*)VXL_NULLPTR, // E: Ax + &JOB, + &info); + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx +index 025e0f07cc..dd4d49bc91 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx +@@ -29,7 +29,7 @@ void sse_op_callback(const long* n, + const double* p, + double* q) + { +- assert(current_system != 0); ++ assert(current_system != VXL_NULLPTR); + + current_system->CalculateProduct(*n,*m,p,q); + } +@@ -46,7 +46,7 @@ void sse_iovect_callback(const long* n, + const long* j, + const long* k) + { +- assert(current_system != 0); ++ assert(current_system != VXL_NULLPTR); + + if (*k==0) + current_system->SaveVectors(*n,*m,q,*j-*m); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx +index bb20b6b7e8..a2e7c825b4 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx +@@ -45,7 +45,7 @@ vnl_svd_economy::vnl_svd_economy( vnl_matrix const& M ) : + vnl_linpack_svdc_economy((real_t*)X, &m_, &m_, &n_, + wspace.data_block(), + espace.data_block(), +- 0, &ldu, ++ VXL_NULLPTR, &ldu, + vspace.data_block(), &n_, + work.data_block(), + &job, &info); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx +index 625b9b51b8..592a05a8af 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx +@@ -17,7 +17,7 @@ + const unsigned nstests = 10; + + +-void fill_with_rng(double * begin, double * end, double a, double b, vnl_random &rng) ++void fill_with_rng(double * begin, const double * end, double a, double b, vnl_random &rng) + { + while (begin != end) + { +@@ -26,7 +26,7 @@ void fill_with_rng(double * begin, double * end, double a, double b, vnl_random + } + } + +-void fill_with_rng(float * begin, float * end, float a, float b, vnl_random &rng) ++void fill_with_rng(float * begin, const float * end, float a, float b, vnl_random &rng) + { + while (begin != end) + { +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx +index b269ba6ba6..db889e64fc 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx +@@ -15,10 +15,10 @@ + // --- dynamic ------------------------------ + + #define NewMat(mat, r,c,data) \ +- assert( sizeof(data) >= r*c*sizeof(double) ); \ ++ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ + vnl_matrix mat( data, r, c ) + #define NewVec(vec, n,data) \ +- assert( sizeof(data) >= n*sizeof(double) ); \ ++ assert( sizeof(data) >= (n)*sizeof(double) ); \ + vnl_vector vec( data, n ) + + static +@@ -35,10 +35,10 @@ test_arithmetic_dynamic() + // --- ref ---------------------------------- + + #define NewMat(mat, r,c,data) \ +- assert( sizeof(data) >= r*c*sizeof(double) ); \ ++ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ + vnl_matrix_ref mat( r, c, data ) + #define NewVec(vec, n,data) \ +- assert( sizeof(data) >= n*sizeof(double) ); \ ++ assert( sizeof(data) >= (n)*sizeof(double) ); \ + vnl_vector_ref vec( n, data ) + + static +@@ -55,10 +55,10 @@ test_arithmetic_ref() + #undef NewVec + + #define NewMat(mat, r,c,data) \ +- assert( sizeof(data) >= r*c*sizeof(double) ); \ ++ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ + vnl_matrix_fixed mat( data ) + #define NewVec(vec, n,data) \ +- assert( sizeof(data) >= n*sizeof(double) ); \ ++ assert( sizeof(data) >= (n)*sizeof(double) ); \ + vnl_vector_fixed vec( data ) + + void +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx +index 4b60e8a01d..a6502a2243 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx +@@ -32,7 +32,7 @@ + // get a byte-swapped file, short of reading in a native file and swapping it + // and writing it back out, and that isn't any easier. + void matlab_write_swapped(std::ostream &f, +- float *array, ++ const float *array, + unsigned size, + char const *name) + { +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx +index 8919c4a4fc..2fdac67c58 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx +@@ -62,7 +62,7 @@ void test_int() + try { m0.get(0,25); } // Raise out of bounds exception. + catch(...) { exceptionThrownAndCaught = true; } + TEST("Out of bounds get(0,25)", exceptionThrownAndCaught, true); +- ++ + exceptionThrownAndCaught = false; + try { m0.get(25,0); } // Raise out of bounds exception. + catch(...) { exceptionThrownAndCaught = true; } +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx +index 7f371724e6..aed9edafb4 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx +@@ -9,9 +9,9 @@ + + + #define print_hex(p) \ +- std::hex<(&p)[sizeof(p)-1]; \ ++ std::hex<(&(p))[sizeof(p)-1]; \ + for (unsigned int i=2; i<=sizeof(p); ++i) \ +- std::cout<(&p))[sizeof(p)-i]; \ ++ std::cout<(&(p)))[sizeof(p)-i]; \ + std::cout<(&p)[sizeof(p)-1]; \ ++ std::hex<(&(p))[sizeof(p)-1]; \ + for (unsigned int i=2; i<=sizeof(p); ++i) \ +- std::cout<(&p))[sizeof(p)-i]; \ ++ std::cout<(&(p)))[sizeof(p)-i]; \ + std::cout<(0)); ++ TEST("==", z_int==0L, true); ++ vnl_rational z_uint(static_cast(0) ); ++ TEST("==", z_uint==0L, true); ++ ++ vnl_rational z_short(static_cast(0)); ++ TEST("==", z_short==0L, true); ++ vnl_rational z_ushort(static_cast(0) ); ++ TEST("==", z_ushort==0L, true); ++ ++ vnl_rational z_long(static_cast(0)); ++ TEST("==", z_long==0L, true); ++ vnl_rational z_ulong(static_cast(0)); ++ TEST("==", z_ulong==0L, true); ++#if 0 ++ vnl_rational z_mixed(static_cast(0), static_cast(1) ); ++ TEST("==", z_mixed==0L, true); ++#endif ++ + TEST("==", a==-5L, true); + TEST("==", 5L==-a, true); + TEST("==", b==-7, true); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx +index b49115fe54..a77f7b4518 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx +@@ -83,7 +83,7 @@ void test_int() + try { sm1.get(0,25); } // Raise out of bounds exception. + catch(...) { exceptionThrownAndCaught = true; } + TEST("Out of bounds get(0,25)", exceptionThrownAndCaught, true); +- ++ + exceptionThrownAndCaught = false; + try { sm1.get(25,0); } // Raise out of bounds exception. + catch(...) { exceptionThrownAndCaught = true; } +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx +index e5ec177ee1..2d6af99d6e 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx +@@ -153,8 +153,8 @@ template VNL_EXPORT void vnl_c_na_vector_inf_norm(T const *, unsigned, S *) + #undef VNL_C_NA_VECTOR_INSTANTIATE_ordered + #define VNL_C_NA_VECTOR_INSTANTIATE_ordered(T) \ + VNL_C_NA_VECTOR_INSTANTIATE_norm(T, vnl_c_na_vector::abs_t); \ +-template class VNL_EXPORT vnl_c_na_vector; \ +-template VNL_EXPORT std::ostream& print_na_vector(std::ostream &,T const *,unsigned) ++template class vnl_c_na_vector; \ ++template std::ostream& print_na_vector(std::ostream &,T const *,unsigned) + + + #undef VNL_C_NA_VECTOR_INSTANTIATE_unordered +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx +index eb558a937a..37e1221e85 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx +@@ -441,7 +441,7 @@ template VNL_EXPORT void vnl_c_vector_inf_norm(T const *, unsigned, S *) + #undef VNL_C_VECTOR_INSTANTIATE_ordered + #define VNL_C_VECTOR_INSTANTIATE_ordered(T) \ + VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector::abs_t); \ +-template class VNL_EXPORT vnl_c_vector; \ ++template class vnl_c_vector; \ + template VNL_EXPORT std::ostream& print_vector(std::ostream &,T const *,unsigned) + + #undef VNL_C_VECTOR_INSTANTIATE_unordered +@@ -450,7 +450,7 @@ VCL_DO_NOT_INSTANTIATE(T vnl_c_vector::max_value(T const *, unsigned), T(0)) + VCL_DO_NOT_INSTANTIATE(T vnl_c_vector::min_value(T const *, unsigned), T(0)); \ + VCL_DO_NOT_INSTANTIATE(unsigned vnl_c_vector::arg_max(T const *, unsigned), 0U); \ + VCL_DO_NOT_INSTANTIATE(unsigned vnl_c_vector::arg_min(T const *, unsigned), 0U); \ +-template class VNL_EXPORT vnl_c_vector; \ ++template class vnl_c_vector; \ + VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector::abs_t); + + #ifndef DOXYGEN_SHOULD_SKIP_THIS +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h +index e831cfb116..7ee40fb0e2 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h +@@ -30,7 +30,7 @@ class VNL_TEMPLATE_EXPORT vnl_file_matrix : public vnl_matrix + vnl_file_matrix(char const* filename); + + operator safe_bool () const +- { return (ok_)? VCL_SAFE_BOOL_TRUE : 0; } ++ { return (ok_)? VCL_SAFE_BOOL_TRUE : VXL_NULLPTR; } + bool operator!() const + { return !ok_; } + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h +index 99cd366e85..8d5c9a78bf 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h +@@ -31,7 +31,7 @@ class VNL_TEMPLATE_EXPORT vnl_file_vector : public vnl_vector + vnl_file_vector(char const* filename); + + operator safe_bool () const +- { return (ok_)? VCL_SAFE_BOOL_TRUE : 0; } ++ { return (ok_)? VCL_SAFE_BOOL_TRUE : VXL_NULLPTR; } + bool operator!() const + { return !ok_; } + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx +index 1f6bd5f718..8d3f9a8cfc 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx +@@ -26,7 +26,7 @@ + #endif + + #elif VXL_HAS_STD_ISFINITE || VXL_HAS_STD_ISNAN || VXL_HAS_STD_ISNORMAL +-# include ++# include + # if VXL_HAS_STD_ISFINITE + # define finite std::isfinite + # define finitef std::isfinite +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h +index 4a7e4a7669..c66e3df9ab 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h +@@ -153,41 +153,28 @@ namespace vnl_math + namespace vnl_math + { + #if VXL_FULLCXX11SUPPORT +- // Prefer to use perfect forwarding to the std library if C++11 features are available. +- //http://stackoverflow.com/questions/9864125/c11-how-to-alias-a-function +- template +- auto isnan(Args&&... args) -> decltype(std::isnan(std::forward(args)...)) { +- return std::isnan(std::forward(args)...); ++ using std::isnan; ++ // Ensure proper conversion to bool type. ++ // Return a signed integer type has been seen with the following ++ // compilers/libstdc++: ++ // g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1) ++ // g++ (GCC) 6.3.1 20170216 (Red Hat 6.3.1-3) ++ template ++ bool isinf(TArg&& arg) ++ { ++ return bool(std::isinf(std::forward(arg))); + } +- template +- auto isinf(Args&&... args) -> decltype(std::isinf(std::forward(args)...)) { +- return std::isinf(std::forward(args)...); +- } +- template +- auto isfinite(Args&&... args) -> decltype(std::isfinite(std::forward(args)...)) { +- return std::isfinite(std::forward(args)...); +- } +- template +- auto isnormal(Args&&... args) -> decltype(std::isnormal(std::forward(args)...)) { +- return std::isnormal(std::forward(args)...); +- } +- template +- auto max(Args&&... args) -> decltype(std::max(std::forward(args)...)) { +- return std::max(std::forward(args)...); +- } +- template +- auto min(Args&&... args) -> decltype(std::min(std::forward(args)...)) { +- return std::min(std::forward(args)...); +- } +- //cbrt is defined in C++11 +- template +- auto cuberoot(Args&&... args) -> decltype(std::cbrt(std::forward(args)...)) { +- return std::cbrt(std::forward(args)...); +- } +- template +- auto hypot(Args&&... args) -> decltype(std::hypot(std::forward(args)...)) { +- return std::hypot(std::forward(args)...); ++ using std::isfinite; ++ using std::isnormal; ++ using std::max; ++ using std::min; ++ using std::cbrt; ++ template ++ TArg cuberoot(TArg&& arg) ++ { ++ return std::cbrt(std::forward(arg)); + } ++ using std::hypot; + #else + // isnan + inline bool isnan(char) { return false; } +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h +index d818e12015..c001352b08 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h +@@ -46,7 +46,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_diag_matrix const&, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + //: print a vnl_matrix. +@@ -54,7 +54,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_matrix const&, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + //: print a vnl_matrix_fixed. +@@ -62,7 +62,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_matrix_fixed const&, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + //: print a vnl_matrix_ref. +@@ -70,7 +70,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_matrix_ref const &, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + //: print a vnl_vector. +@@ -78,7 +78,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_vector const &, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + //: print a vnl_vector_fixed. +@@ -86,7 +86,7 @@ std::ostream &vnl_matlab_print(std::ostream &, + template VNL_TEMPLATE_EXPORT + std::ostream &vnl_matlab_print(std::ostream &, + vnl_vector_fixed const &, +- char const *variable_name =0, ++ char const *variable_name =VXL_NULLPTR, + vnl_matlab_print_format =vnl_matlab_print_format_default); + + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h +index bdac336023..061e7b0e11 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h +@@ -61,7 +61,7 @@ template + inline + vnl_matlab_print_proxy + vnl_matlab_print(T const &obj, +- char const *name = 0, ++ char const *name = VXL_NULLPTR, + vnl_matlab_print_format format = vnl_matlab_print_format_default) + { + return vnl_matlab_print_proxy(obj, name, format); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h +index 788c583ab8..5e56ac93d4 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h +@@ -33,8 +33,8 @@ template class vnl_matrix; + // If the data in the file cannot reasonably be read into the destination, abort(). + // + // The vector/matrix will be resized if necessary. +-template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_vector &, char const *name =0); +-template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_matrix &, char const *name =0); ++template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_vector &, char const *name =VXL_NULLPTR); ++template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_matrix &, char const *name =VXL_NULLPTR); + + // ------------------------------ less easy ------------------------------ + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx +index a48b31f269..5f276ef576 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx +@@ -536,7 +536,7 @@ vnl_matrix_fixed_ref::read_ascii(std::istream& s) const + + template + vnl_matrix_fixed_ref & +-vnl_matrix_fixed_ref::flipud() ++vnl_matrix_fixed_ref::flipud() + { + for (unsigned int r1 = 0; 2*r1+1 < nrows; ++r1) + { +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx +index 72046e8162..0fc9533336 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx +@@ -57,7 +57,7 @@ VXL_CONSTEXPR_VAR unsigned long long vnl_numeric_traits::one + #endif + + VXL_CONSTEXPR_VAR bool vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(true); +-VXL_CONSTEXPR_VAR char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(char(255)<0?127:255); ++VXL_CONSTEXPR_VAR char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(char(255)<0?127:char(255)); + // It is 127 when "char" is signed and 255 when "char" is unsigned. + VXL_CONSTEXPR_VAR unsigned char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(255); + VXL_CONSTEXPR_VAR signed char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(127); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx +index cd3e202c38..8cdb8f8582 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx +@@ -89,7 +89,7 @@ void vnl_random::reseed(unsigned long seed) + for (int j=0;j<1000;j++) lrand32(); + } + +-void vnl_random::reseed(unsigned long seed[vnl_random_array_size]) ++void vnl_random::reseed(const unsigned long seed[vnl_random_array_size]) + { + mz_array_position = 0UL; + mz_borrow = 0L; +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h +index faaa00a187..de5391ac8a 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h +@@ -81,7 +81,7 @@ class VNL_EXPORT vnl_random + void reseed(unsigned long); + + //: Starts a new deterministic sequence from an already declared generator using the provided seed. +- void reseed(unsigned long[vnl_random_array_size]); ++ void reseed(const unsigned long[vnl_random_array_size]); + + //: This restarts the sequence of random numbers. + // Restarts so that it repeats +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx +index a43759f0ab..293fd07b87 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx +@@ -6,9 +6,8 @@ + #include // for vnl_numeric_traits::maxval + #include + +-//: Creates a rational from a double. +-// This is done by computing the continued fraction approximation for d. +-vnl_rational::vnl_rational(double d) ++template ++inline void makeNumDen( FloatingType d, long &num_, long &den_) + { + bool sign = d<0; + if (sign) d = -d; +@@ -29,6 +28,20 @@ vnl_rational::vnl_rational(double d) + // no need to normalize() since prev_num and prev_den have guaranteed a gcd=1 + } + ++//: Creates a rational from a double. ++// This is done by computing the continued fraction approximation for d. ++vnl_rational::vnl_rational(double d) ++{ ++ makeNumDen(d,num_,den_); ++} ++ ++//: Creates a rational from a double. ++// This is done by computing the continued fraction approximation for d. ++vnl_rational::vnl_rational(float f) ++{ ++ makeNumDen(f,num_,den_); ++} ++ + //: Multiply/assign: replace lhs by lhs * rhs + // Note that 0 * Inf and Inf * 0 are undefined. + // Also note that there could be integer overflow during this calculation! +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h +index f36caab39a..9afa439ee5 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h +@@ -80,21 +80,45 @@ class VNL_EXPORT vnl_rational + // Also serves as automatic cast from long to vnl_rational. + // The only input which is not allowed is (0,0); + // the denominator is allowed to be 0, to represent +Inf or -Inf. +- inline vnl_rational(long num = 0L, long den = 1L) ++ ++ inline vnl_rational() ++ : num_(0L), den_(1L) { normalize(); } ++ ++ inline vnl_rational(long num) ++ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(long num, long den) + : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } +- //: Creates a rational with given numerator and denominator. +- // Note these are not automatic type conversions because of a bug +- // in the Borland compiler. Since these just convert their +- // arguments to long anyway, there is no harm in letting +- // the long overload be used for automatic conversions. +- explicit inline vnl_rational(int num, int den = 1) ++ ++ inline vnl_rational(unsigned long num) ++ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(unsigned long num, unsigned long den) ++ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } ++ ++ inline vnl_rational(int num) ++ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(int num, int den) + : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } +- explicit inline vnl_rational(unsigned int num, unsigned int den = 1) ++ ++ inline vnl_rational(unsigned int num) ++ : num_((long)num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(unsigned int num, unsigned int den) + : num_((long)num), den_((long)den) { assert(num!=0||den!=0); normalize(); } ++ ++ inline vnl_rational(short num) ++ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(short num, short den) ++ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } ++ ++ inline vnl_rational(unsigned short num) ++ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } ++ inline vnl_rational(unsigned short num, unsigned short den) ++ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } ++ + //: Creates a rational from a double. + // This is done by computing the continued fraction approximation for d. + // Note that this is explicitly \e not an automatic type conversion. +- explicit vnl_rational(double d); ++ vnl_rational(double d); ++ vnl_rational(float d); + // Copy constructor + inline vnl_rational(vnl_rational const& from) + : num_(from.numerator()), den_(from.denominator()) {} +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx +index e699962126..9d5d745436 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx +@@ -11,7 +11,7 @@ + #include + #include + +-#include // dont_vxl_filter ++#include // dont_vxl_filter + + #if !VXL_STDLIB_HAS_DRAND48 + // rand() is not always a good random number generator, +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h +index a3429de673..d012cf7b73 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h +@@ -94,7 +94,7 @@ class VNL_TEMPLATE_EXPORT vnl_sparse_matrix_pair + return *this; + } + +- struct less : public std::binary_function ++ struct less + { + bool operator() (vnl_sparse_matrix_pair const& p1, vnl_sparse_matrix_pair const& p2) { + return p1.first < p2.first; +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx +index 7584d8da9e..608b488339 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx +@@ -77,6 +77,6 @@ void vnl_sparse_matrix_linear_system::apply_preconditioner(vnl_vector + px = dot_product(x,jacobi_precond_); + } + +-template class VNL_EXPORT vnl_sparse_matrix_linear_system; +-template class VNL_EXPORT vnl_sparse_matrix_linear_system; ++template class vnl_sparse_matrix_linear_system; ++template class vnl_sparse_matrix_linear_system; + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h +index 8fbe755e74..091425bd8f 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h +@@ -35,8 +35,6 @@ class VNL_TEMPLATE_EXPORT vnl_sparse_matrix_linear_system : public vnl_linear_sy + vnl_sparse_matrix_linear_system(vnl_sparse_matrix const& A, vnl_vector const& b) : + vnl_linear_system(A.columns(), A.rows()), A_(A), b_(b), jacobi_precond_() {} + +- virtual ~vnl_sparse_matrix_linear_system() {} +- + //: Implementations of the vnl_linear_system virtuals. + void multiply(vnl_vector const& x, vnl_vector & b) const; + //: Implementations of the vnl_linear_system virtuals. +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h +index e06ef30d33..bfc4a3a733 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h +@@ -77,8 +77,8 @@ + # define VNL_SSE_HEAP_STORE(pf) _mm_storeu_##pf + # define VNL_SSE_HEAP_LOAD(pf) _mm_loadu_##pf + # if VNL_CONFIG_THREAD_SAFE +-# define VNL_SSE_ALLOC(n,s,a) new char[n*s] +-# define VNL_SSE_FREE(v,n,s) delete [] static_cast(v) ++# define VNL_SSE_ALLOC(n,s,a) new char[(n)*(s)] ++# define VNL_SSE_FREE(v,n,s) (delete [] static_cast(v)) + # else + # define VNL_SSE_ALLOC(n,s,a) vnl_alloc::allocate((n == 0) ? 8 : (n * s)); + # define VNL_SSE_FREE(v,n,s) if (v) vnl_alloc::deallocate(v, (n == 0) ? 8 : (n * s)); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h +index d1adbb1d8a..3922fca8eb 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h +@@ -29,7 +29,7 @@ class VNL_TEMPLATE_EXPORT vnl_sym_matrix + { + public: + //: Construct an empty symmetric matrix. +- vnl_sym_matrix(): data_(0), index_(0), nn_(0) {} ++ vnl_sym_matrix(): data_(VXL_NULLPTR), index_(VXL_NULLPTR), nn_(0) {} + + //: Construct a symmetric matrix of size nn by nn. + explicit vnl_sym_matrix(unsigned nn): +@@ -222,7 +222,7 @@ inline vnl_sym_matrix::vnl_sym_matrix(vnl_matrix const& that): + + template + inline vnl_sym_matrix::vnl_sym_matrix(vnl_sym_matrix const& that): +- data_(0), index_(0), nn_(0) ++ data_(VXL_NULLPTR), index_(VXL_NULLPTR), nn_(0) + { + set_size(that.rows()); + update(that); +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h +index 3fb0a9207f..5053a4e172 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h +@@ -134,7 +134,7 @@ class VNL_TEMPLATE_EXPORT vnl_vector + vnl_vector(vnl_vector const &, vnl_matrix const &, vnl_tag_mul); // v * M + vnl_vector(vnl_vector &that, vnl_tag_grab) + : num_elmts(that.num_elmts), data(that.data) +- { that.num_elmts=0; that.data=0; } // "*this" now uses "that"'s data. ++ { that.num_elmts=0; that.data=VXL_NULLPTR; } // "*this" now uses "that"'s data. + // + #endif + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx +index 0e995a8ce3..1af97626ca 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx +@@ -65,7 +65,7 @@ + #define vnl_vector_alloc_blah(size) \ + do { \ + this->num_elmts = (size); \ +- this->data = size ? vnl_c_vector::allocate_T(size) : 0; \ ++ this->data = (size) ? vnl_c_vector::allocate_T(size) : 0; \ + } while (false) + + // This macro deallocates the dynamic storage used by a vnl_vector. +@@ -288,7 +288,7 @@ void vnl_vector::clear() + if (data) { + destroy(); + num_elmts = 0; +- data = 0; ++ data = VXL_NULLPTR; + } + } + +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx +index 7317b90c72..13879ea79a 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx +@@ -123,7 +123,7 @@ vnl_vector_fixed_ref_const::print( std::ostream& s ) const + // instantiation macros for vnl_vector_fixed_ref : + + #define VNL_VECTOR_FIXED_REF_INSTANTIATE(T,n) \ +-template class VNL_EXPORT vnl_vector_fixed_ref; \ +-template class VNL_EXPORT vnl_vector_fixed_ref_const ++template class vnl_vector_fixed_ref; \ ++template class vnl_vector_fixed_ref_const + + #endif // vnl_vector_fixed_ref_hxx_ +diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h b/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h +index 152aeab849..a37ecc38b7 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h ++++ b/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h +@@ -26,9 +26,9 @@ + + //: Version date. This is updated every day. + // Formats are year=CCYY, month=MM, day=DD +-#define VXL_VERSION_DATE_YEAR 2017 +-#define VXL_VERSION_DATE_MONTH 12 +-#define VXL_VERSION_DATE_DAY 08 ++#define VXL_VERSION_DATE_YEAR 2018 ++#define VXL_VERSION_DATE_MONTH 05 ++#define VXL_VERSION_DATE_DAY 16 + + //: Helper macros to create strings with the preprocessor. + #define VXL_VERSION_TO_STRING(s) VXL_VERSION_TO_STRING0(s) +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt +index 431bbae68a..f9f4816083 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt +@@ -445,7 +445,6 @@ if(BUILD_TESTING) + add_subdirectory(tests) + endif() + +-# Disabled in ITK to avoid find_package(X11) +-if(BUILD_EXAMPLES AND 0) ++if(BUILD_EXAMPLES) + add_subdirectory(examples) + endif() +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat +index 2ae4565113..0dc84531c9 100755 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat +@@ -1,5 +1,5 @@ +-%1 %2 %3 %4 %5 %6 %7 %8 %9 +-if errorlevel 1 goto nolonglong +-exit 0 +-:nolonglong +-%1 -DNO_LONG_LONG %2 %3 %4 %5 %6 %7 %8 %9 ++%1 %2 %3 %4 %5 %6 %7 %8 %9 ++if errorlevel 1 goto nolonglong ++exit 0 ++:nolonglong ++%1 -DNO_LONG_LONG %2 %3 %4 %5 %6 %7 %8 %9 +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat +index 69be841b91..2c11a97e45 100755 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat +@@ -1,5 +1,5 @@ +-%1 -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 +-if errorlevel 1 goto nolonglong +-exit 0 +-:nolonglong +-%1 -DNO_LONG_LONG -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 ++%1 -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 ++if errorlevel 1 goto nolonglong ++exit 0 ++:nolonglong ++%1 -DNO_LONG_LONG -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx +index 6053b93203..067b1abebb 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx +@@ -16,6 +16,7 @@ + * + *=========================================================================*/ + #include "lsmrBase.h" ++#include "vcl_compiler_detection.h" + + #include + #include +@@ -40,7 +41,7 @@ lsmrBase::lsmrBase() + this->btol = 1e-6; + this->conlim = 1.0 / ( 10 * sqrt( this->eps ) ); + this->itnlim = 10; +- this->nout = NULL; ++ this->nout = VXL_NULLPTR; + this->istop = 0; + this->itn = 0; + this->normA = 0.0; +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx +index 799bc0538b..b0ccf84890 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx +@@ -16,10 +16,11 @@ + * + *=========================================================================*/ + #include "lsmrDense.h" ++#include "vcl_compiler_detection.h" + + lsmrDense::lsmrDense() + { +- this->A = 0; ++ this->A = VXL_NULLPTR; + } + + +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx +index c62c3953a8..8d55fc088a 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx +@@ -17,10 +17,11 @@ + *=========================================================================*/ + + #include "lsqrDense.h" ++#include "vcl_compiler_detection.h" + + lsqrDense::lsqrDense() + { +- this->A = 0; ++ this->A = VXL_NULLPTR; + } + + +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h +index 38300975a4..c30ff15ac8 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h +@@ -175,15 +175,15 @@ + * Macro function that adds data to a imaginary element in the matrix by + * a pointer. + */ +-#define spADD_IMAG_ELEMENT(element,imag) *(element+1) += imag ++#define spADD_IMAG_ELEMENT(element,imag) *((element)+1) += imag + + /*! + * Macro function that adds data to a complex element in the matrix by + * a pointer. + */ + #define spADD_COMPLEX_ELEMENT(element,real,imag) \ +-{ *(element) += real; \ +- *(element+1) += imag; \ ++{ *(element) += (real); \ ++ *((element)+1) += (imag); \ + } + + /*! +@@ -191,10 +191,10 @@ + * specified by the given template. + */ + #define spADD_REAL_QUAD(template,real) \ +-{ *((template).Element1) += real; \ +- *((template).Element2) += real; \ +- *((template).Element3Negated) -= real; \ +- *((template).Element4Negated) -= real; \ ++{ *((template).Element1) += (real); \ ++ *((template).Element2) += (real); \ ++ *((template).Element3Negated) -= (real); \ ++ *((template).Element4Negated) -= (real); \ + } + + /*! +@@ -202,10 +202,10 @@ + * elements specified by the given template. + */ + #define spADD_IMAG_QUAD(template,imag) \ +-{ *((template).Element1+1) += imag; \ +- *((template).Element2+1) += imag; \ +- *((template).Element3Negated+1) -= imag; \ +- *((template).Element4Negated+1) -= imag; \ ++{ *((template).Element1+1) += (imag); \ ++ *((template).Element2+1) += (imag); \ ++ *((template).Element3Negated+1) -= (imag); \ ++ *((template).Element4Negated+1) -= (imag); \ + } + + /*! +@@ -213,14 +213,14 @@ + * elements specified by the given template. + */ + #define spADD_COMPLEX_QUAD(template,real,imag) \ +-{ *((template).Element1) += real; \ +- *((template).Element2) += real; \ +- *((template).Element3Negated) -= real; \ +- *((template).Element4Negated) -= real; \ +- *((template).Element1+1) += imag; \ +- *((template).Element2+1) += imag; \ +- *((template).Element3Negated+1) -= imag; \ +- *((template).Element4Negated+1) -= imag; \ ++{ *((template).Element1) += (real); \ ++ *((template).Element2) += (real); \ ++ *((template).Element3Negated) -= (real); \ ++ *((template).Element4Negated) -= (real); \ ++ *((template).Element1+1) += (imag); \ ++ *((template).Element2+1) += (imag); \ ++ *((template).Element3Negated+1) -= (imag); \ ++ *((template).Element4Negated+1) -= (imag); \ + } + + /* +diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c +index e9b55d33d5..b11058fd9d 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c ++++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c +@@ -9232,6 +9232,8 @@ int arraysize; + } + /* Choose a random pivot to split the array. */ + pivot = (int) randomnation((unsigned int) arraysize); ++ if (pivot == arraysize)//JLM without this test, pivot can equal arraysize and segfault ++ pivot--; + pivotx = sortarray[pivot][0]; + pivoty = sortarray[pivot][1]; + /* Split the array. */ +@@ -9308,6 +9310,8 @@ int axis; + } + /* Choose a random pivot to split the array. */ + pivot = (int) randomnation((unsigned int) arraysize); ++ if (pivot == arraysize)//JLM/SES without this test, pivot can equal arraysize and segfault ++ pivot--; + pivot1 = sortarray[pivot][axis]; + pivot2 = sortarray[pivot][1 - axis]; + /* Split the array. */ +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt +index 89e2b99f71..fed3b8e268 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt +@@ -73,7 +73,7 @@ if( VXL_MANUAL_GENERATE_NEW_COMPILER_DETECTION_HEADERS ) + cxx_long_long_type # long long type, as defined in N1811. + cxx_noexcept # Exception specifications, as defined in N3050. + cxx_nonstatic_member_init # Non-static data member initialization, as defined in N2756. +- cxx_nullptr # Null pointer, as defined in N2431. ++ cxx_VXL_NULLPTR # Null pointer, as defined in N2431. + cxx_override # Override control override keyword, as defined in N2928, N3206 and N3272. + cxx_range_for # Range-based for, as defined in N2930. + cxx_raw_string_literals # Raw string literals, as defined in N2442. +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h +index 196ab2d503..7ff70236c4 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h +@@ -226,7 +226,7 @@ + # define VXL_COMPILER_CXX_NONSTATIC_MEMBER_INIT 0 + # endif + +-# if ((__clang_major__ * 100) + __clang_minor__) >= 400 && __has_feature(cxx_nullptr) ++# if ((__clang_major__ * 100) + __clang_minor__) >= 400 && __has_feature(cxx_VXL_NULLPTR) + # define VXL_COMPILER_CXX_NULLPTR 1 + # else + # define VXL_COMPILER_CXX_NULLPTR 0 +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h +index 752ad86223..cae90561d2 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h +@@ -225,7 +225,7 @@ + # define VXL_COMPILER_CXX_NONSTATIC_MEMBER_INIT 0 + # endif + +-# if ((__clang_major__ * 100) + __clang_minor__) >= 301 && __has_feature(cxx_nullptr) ++# if ((__clang_major__ * 100) + __clang_minor__) >= 301 && __has_feature(cxx_VXL_NULLPTR) + # define VXL_COMPILER_CXX_NULLPTR 1 + # else + # define VXL_COMPILER_CXX_NULLPTR 0 +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx +index 43ba3e5feb..605e73114a 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx +@@ -1,7 +1,7 @@ + #include + #include + +-#define TEST(str,x,y) vcl_printf(str ": "); if (x!=y) { vcl_printf("FAILED\n"); status = 1; } else { vcl_printf("PASSED\n"); } ++#define TEST(str,x,y) vcl_printf(str ": "); if ((x)!=(y)) { vcl_printf("FAILED\n"); status = 1; } else { vcl_printf("PASSED\n"); } + + int test_atomic_count_main(int /*argc*/,char* /*argv*/[]) + { +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx +index 5ca2b758e6..ebc552b521 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx +@@ -24,7 +24,7 @@ int test_cmath_main(int /*argc*/,char* /*argv*/[]) + + #define macro(var, type) \ + do { \ +- if (vcl_abs(var) == var && vcl_abs(- var) == var) \ ++ if (vcl_abs(var) == (var) && vcl_abs(- (var)) == (var)) \ + vcl_cout << "vcl_abs(" #type ") PASSED" << vcl_endl; \ + else \ + vcl_cerr << "vcl_abs(" #type ") *** FAILED *** " << vcl_endl; \ +@@ -58,7 +58,7 @@ do { \ + do { \ + T x = 2; \ + T y = vcl_sqrt(x); \ +- if (vcl_abs(x - y*y) < eps) \ ++ if (vcl_abs(x - y*y) < (eps)) \ + vcl_cout << "vcl_sqrt(" #T ") PASSED" << vcl_endl; \ + else \ + vcl_cout << "vcl_sqrt(" #T ") *** FAILED *** " << vcl_endl; \ +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx +index 4d4fb1aa24..40ed03dd02 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx +@@ -49,8 +49,8 @@ void test_static_const_definition() + #undef TEST_TYPE + } + +-#define TEST(m,x,y) if ((x)!=(y)) { vcl_cout<< "FAIL: " << m << '\n'; fail=true; } \ +- else { vcl_cout<< "PASS: " << m << '\n'; } ++#define TEST(m,x,y) if ((x)!=(y)) { vcl_cout<< "FAIL: " << (m) << '\n'; fail=true; } \ ++ else { vcl_cout<< "PASS: " << (m) << '\n'; } + + int test_limits_main(int /*argc*/, char* /*argv*/[]) + { +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx +index a76e92d467..b87977af9f 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx +@@ -14,14 +14,14 @@ struct A + + struct B: public A {}; + +-static int function_call(vcl_auto_ptr a) ++static int function_call(vcl_unique_ptr a) + { + return a.get()? 1:0; + } + + static A* get_A(A& a) { return &a; } + +-static vcl_auto_ptr generate_auto_ptr () { return vcl_auto_ptr(new A); } ++static vcl_unique_ptr generate_auto_ptr () { return vcl_unique_ptr(new A); } + + int test_memory_main(int /*argc*/,char* /*argv*/[]) + { +@@ -29,11 +29,11 @@ int test_memory_main(int /*argc*/,char* /*argv*/[]) + + // Keep everything in a subscope so we can detect leaks. + { +- vcl_auto_ptr pa0; +- vcl_auto_ptr pa1(new A()); +- vcl_auto_ptr pb1(new B()); +- vcl_auto_ptr pa2(new B()); +- vcl_auto_ptr pa3(pb1); ++ vcl_unique_ptr pa0; ++ vcl_unique_ptr pa1(new A()); ++ vcl_unique_ptr pb1(new B()); ++ vcl_unique_ptr pa2(new B()); ++ vcl_unique_ptr pa3(vcl_move(pb1)); + + A* ptr = get_A(*pa1); + ASSERT(ptr == pa1.get(), +@@ -55,12 +55,12 @@ int test_memory_main(int /*argc*/,char* /*argv*/[]) + delete pa0.release(); + ASSERT(!pa0.get(), "auto_ptr holds an object after release()"); + +- pa1 = pa3; ++ pa1 = vcl_move(pa3); + ASSERT(!pa3.get(), "auto_ptr holds an object after assignment to another"); + ASSERT(pa1.get(), + "auto_ptr does not hold an object after assignment from another"); + +- int copied = function_call(pa2); ++ int copied = function_call(vcl_move(pa2)); + ASSERT(copied, "auto_ptr did not receive ownership in called function"); + ASSERT(!pa2.get(), "auto_ptr did not release ownership to called function"); + +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx +index 32e454954d..9bbbe02526 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx +@@ -2,7 +2,7 @@ + #include + #include + +-#define AssertEq(x,y) {status+=((x)==(y))?0:1;vcl_cout<<"TEST ["< 2 ) ++# define VCL_GCC_83 ++# elif (__GNUC_MINOR__ > 1 ) ++# define VCL_GCC_82 ++# elif (__GNUC_MINOR__ > 0 ) ++# define VCL_GCC_81 ++# else ++# define VCL_GCC_80 ++# endif + # else + # error "Dunno about this gcc" + # endif +@@ -897,7 +908,7 @@ __inline int vcl_snprintf(char *outBuf, size_t size, const char *format, ...) + #define vcl_uninitialized_copy std::uninitialized_copy + #define vcl_uninitialized_fill std::uninitialized_fill + #define vcl_uninitialized_fill_n std::uninitialized_fill_n +-#define vcl_auto_ptr std::auto_ptr ++#define vcl_auto_ptr vcl_auto_ptr + #define vcl_bad_alloc std::bad_alloc + #define vcl_set_new_handler std::set_new_handler + #define vcl_accumulate std::accumulate +diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h b/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h +index b15a5f4368..da038dd721 100644 +--- a/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h ++++ b/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h +@@ -2,6 +2,19 @@ + #define vcl_memory_h_ + + #include ++#include + #include "vcl_compiler.h" + ++// Needed to provide backwards compatibility between C++11 and older compilers ++// https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 ++#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER > 540) ++ template ++ using vcl_unique_ptr = std::unique_ptr; ++ #define vcl_move( value ) std::move(value) ++#else ++// NOTE: THIS DOES NOT MEET THE STANDARDS FOR A UNIQUE POINTER! ++# define vcl_unique_ptr std::auto_ptr ++# define vcl_move( value ) value ++#endif ++ + #endif // vcl_memory_h_ diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake index cf66989655..0109ff72a3 100644 --- a/CMakeExternals/ITK.cmake +++ b/CMakeExternals/ITK.cmake @@ -1,77 +1,77 @@ #----------------------------------------------------------------------------- # ITK #----------------------------------------------------------------------------- # Sanity checks if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR}) message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj ITK) set(proj_DEPENDENCIES GDCM) if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() if(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() set(ITK_DEPENDS ${proj}) if(NOT DEFINED ITK_DIR) set(additional_cmake_args -DUSE_WRAP_ITK:BOOL=OFF) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() # Keep the behaviour of ITK 4.3 which by default turned on ITK Review # see MITK bug #17338 list(APPEND additional_cmake_args -DModule_ITKReview:BOOL=ON # for 4.7, the OpenJPEG is needed by review but the variable must be set -DModule_ITKOpenJPEG:BOOL=ON ) if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.13.0.tar.xz URL_MD5 3badf70cfb0093054453f66c5974c5a4 # work with external GDCM - # PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-4.11.0.patch + PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-VNL-2018-05-16.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_EXAMPLES:BOOL=OFF -DITK_USE_SYSTEM_GDCM:BOOL=ON -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_USE_SYSTEM_HDF5:BOOL=ON -DHDF5_DIR:PATH=${HDF5_DIR} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(ITK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/Modules/CEST/src/mitkCustomTagParser.cpp b/Modules/CEST/src/mitkCustomTagParser.cpp index 821ce29ba2..aac507d84a 100644 --- a/Modules/CEST/src/mitkCustomTagParser.cpp +++ b/Modules/CEST/src/mitkCustomTagParser.cpp @@ -1,757 +1,757 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCustomTagParser.h" #include #include #include #include "mitkIPropertyPersistence.h" #include "usGetModuleContext.h" #include "usModule.h" #include "usModuleContext.h" #include "usModuleResource.h" #include "usModuleResourceStream.h" #include #include #include #include #include #include #include #include namespace { mitk::IPropertyPersistence *GetPersistenceService() { mitk::IPropertyPersistence *result = nullptr; std::vector> persRegisters = us::GetModuleContext()->GetServiceReferences(); if (!persRegisters.empty()) { if (persRegisters.size() > 1) { MITK_WARN << "Multiple property description services found. Using just one."; } result = us::GetModuleContext()->GetService(persRegisters.front()); } return result; }; } const std::string mitk::CustomTagParser::m_CESTPropertyPrefix = "CEST."; const std::string mitk::CustomTagParser::m_OffsetsPropertyName = m_CESTPropertyPrefix + "Offsets"; const std::string mitk::CustomTagParser::m_RevisionPropertyName = m_CESTPropertyPrefix + "Revision"; const std::string mitk::CustomTagParser::m_JSONRevisionPropertyName = m_CESTPropertyPrefix + "revision_json"; const std::string mitk::CustomTagParser::m_RevisionIndependentMapping = "\n" " \"sProtConsistencyInfo.tSystemType\" : \"SysType\",\n" " \"sProtConsistencyInfo.flNominalB0\" : \"NominalB0\",\n" " \"sTXSPEC.asNucleusInfo[0].lFrequency\" : \"FREQ\",\n" " \"sTXSPEC.asNucleusInfo[0].flReferenceAmplitude\" : \"RefAmp\",\n" " \"alTR[0]\" : \"TR\",\n" " \"alTE[0]\" : \"TE\",\n" " \"lAverages\" : \"averages\",\n" " \"lRepetitions\" : \"repetitions\",\n" " \"adFlipAngleDegree[0]\" : \"ImageFlipAngle\",\n" " \"lTotalScanTimeSec\" : \"TotalScanTime\","; const std::string mitk::CustomTagParser::m_DefaultJsonString = "{\n" " \"default mapping, corresponds to revision 1416\" : \"revision_json\",\n" " \"sWiPMemBlock.alFree[1]\" : \"AdvancedMode\",\n" " \"sWiPMemBlock.alFree[2]\" : \"RecoveryMode\",\n" " \"sWiPMemBlock.alFree[3]\" : \"DoubleIrrMode\",\n" " \"sWiPMemBlock.alFree[4]\" : \"BinomMode\",\n" " \"sWiPMemBlock.alFree[5]\" : \"MtMode\",\n" " \"sWiPMemBlock.alFree[6]\" : \"PreparationType\",\n" " \"sWiPMemBlock.alFree[7]\" : \"PulseType\",\n" " \"sWiPMemBlock.alFree[8]\" : \"SamplingType\",\n" " \"sWiPMemBlock.alFree[9]\" : \"SpoilingType\",\n" " \"sWiPMemBlock.alFree[10]\" : \"measurements\",\n" " \"sWiPMemBlock.alFree[11]\" : \"NumberOfPulses\",\n" " \"sWiPMemBlock.alFree[12]\" : \"NumberOfLockingPulses\",\n" " \"sWiPMemBlock.alFree[13]\" : \"PulseDuration\",\n" " \"sWiPMemBlock.alFree[14]\" : \"DutyCycle\",\n" " \"sWiPMemBlock.alFree[15]\" : \"RecoveryTime\",\n" " \"sWiPMemBlock.alFree[16]\" : \"RecoveryTimeM0\",\n" " \"sWiPMemBlock.alFree[17]\" : \"ReadoutDelay\",\n" " \"sWiPMemBlock.alFree[18]\" : \"BinomDuration\",\n" " \"sWiPMemBlock.alFree[19]\" : \"BinomDistance\",\n" " \"sWiPMemBlock.alFree[20]\" : \"BinomNumberofPulses\",\n" " \"sWiPMemBlock.alFree[21]\" : \"BinomPreRepetions\",\n" " \"sWiPMemBlock.alFree[22]\" : \"BinomType\",\n" " \"sWiPMemBlock.adFree[1]\" : \"Offset\",\n" " \"sWiPMemBlock.adFree[2]\" : \"B1Amplitude\",\n" " \"sWiPMemBlock.adFree[3]\" : \"AdiabaticPulseMu\",\n" " \"sWiPMemBlock.adFree[4]\" : \"AdiabaticPulseBW\",\n" " \"sWiPMemBlock.adFree[5]\" : \"AdiabaticPulseLength\",\n" " \"sWiPMemBlock.adFree[6]\" : \"AdiabaticPulseAmp\",\n" " \"sWiPMemBlock.adFree[7]\" : \"FermiSlope\",\n" " \"sWiPMemBlock.adFree[8]\" : \"FermiFWHM\",\n" " \"sWiPMemBlock.adFree[9]\" : \"DoubleIrrDuration\",\n" " \"sWiPMemBlock.adFree[10]\" : \"DoubleIrrAmplitude\",\n" " \"sWiPMemBlock.adFree[11]\" : \"DoubleIrrRepetitions\",\n" " \"sWiPMemBlock.adFree[12]\" : \"DoubleIrrPreRepetitions\"\n" "}"; mitk::CustomTagParser::CustomTagParser(std::string relevantFile) : m_ClosestInternalRevision(""), m_ClosestExternalRevision("") { std::string pathToDirectory; std::string fileName; itksys::SystemTools::SplitProgramPath(relevantFile, pathToDirectory, fileName); m_DicomDataPath = pathToDirectory; m_ParseStrategy = "Automatic"; m_RevisionMappingStrategy = "Fuzzy"; } bool mitk::CustomTagParser::IsT1Sequence(std::string preparationType, std::string recoveryMode, std::string spoilingType, std::string revisionString) { bool isT1 = false; // if a forced parse strategy is set, use that one if ("T1" == m_ParseStrategy) { return true; } if ("CEST/WASABI" == m_ParseStrategy) { return false; } if (("T1Recovery" == preparationType) || ("T1Inversion" == preparationType)) { isT1 = true; } // How to interpret the recoveryMode depends on the age of the sequence // older sequences use 0 = false and 1 = true, newer ones 1 = false and 2 = true. // A rough rule of thumb is to assume that if the SpoilingType is 0, then the first // convention is chosen, if it is 1, then the second applies. Otherwise // we assume revision 1485 and newer to follow the new convention. // This unfortunate heuristic is due to somewhat arbitrary CEST sequence implementations. if (!isT1) { std::string thisIsTrue = "1"; std::string thisIsFalse = "0"; if ("0" == spoilingType) { thisIsFalse = "0"; thisIsTrue = "1"; } else if ("1" == spoilingType) { thisIsFalse = "1"; thisIsTrue = "2"; } else { int revisionNrWeAssumeToBeDifferenciating = 1485; if (std::stoi(revisionString) - revisionNrWeAssumeToBeDifferenciating < 0) { thisIsFalse = "0"; thisIsTrue = "1"; } else { thisIsFalse = "1"; thisIsTrue = "2"; } } if (thisIsFalse == recoveryMode) { isT1 = false; } else if (thisIsTrue == recoveryMode) { isT1 = true; } } return isT1; } mitk::PropertyList::Pointer mitk::CustomTagParser::ParseDicomPropertyString(std::string dicomPropertyString) { auto results = mitk::PropertyList::New(); if ("" == dicomPropertyString) { //MITK_ERROR << "Could not parse empty custom dicom string"; return results; } std::map privateParameters; // convert hex to ascii // the Siemens private tag contains the information like this // "43\52\23\34" we jump over each \ and convert the number int len = dicomPropertyString.length(); std::string asciiString; for (int i = 0; i < len; i += 3) { std::string byte = dicomPropertyString.substr(i, 2); auto chr = (char)(int)strtol(byte.c_str(), nullptr, 16); asciiString.push_back(chr); } // extract parameter list std::size_t beginning = asciiString.find("### ASCCONV BEGIN ###") + 21; std::size_t ending = asciiString.find("### ASCCONV END ###"); std::string parameterListString = asciiString.substr(beginning, ending - beginning); boost::replace_all(parameterListString, "\r\n", "\n"); boost::char_separator newlineSeparator("\n"); boost::tokenizer> parameters(parameterListString, newlineSeparator); for (const auto ¶meter : parameters) { std::vector parts; boost::split(parts, parameter, boost::is_any_of("=")); if (parts.size() == 2) { parts[0].erase(std::remove(parts[0].begin(), parts[0].end(), ' '), parts[0].end()); parts[1].erase(parts[1].begin(), parts[1].begin() + 1); // first character is a space privateParameters[parts[0]] = parts[1]; } } // determine what revision we are using to handle parameters appropriately std::string revisionPrefix = "CEST_Rev"; std::string lowerRevisionPrefix = revisionPrefix; std::string lowerParameter = privateParameters["tSequenceFileName"]; std::transform(lowerRevisionPrefix.begin(), lowerRevisionPrefix.end(), lowerRevisionPrefix.begin(), ::tolower ); std::transform(lowerParameter.begin(), lowerParameter.end(), lowerParameter.begin(), ::tolower); std::size_t foundPosition = lowerParameter.find(lowerRevisionPrefix); if (foundPosition == std::string::npos) { MITK_ERROR << "Could not find revision information."; return results; } std::string revisionString = privateParameters["tSequenceFileName"].substr(foundPosition + revisionPrefix.length(), std::string::npos); std::size_t firstNonNumber = revisionString.find_first_not_of("0123456789"); revisionString.erase(firstNonNumber, std::string::npos); results->SetProperty(m_RevisionPropertyName, mitk::StringProperty::New(revisionString)); std::string jsonString = GetRevisionAppropriateJSONString(revisionString); boost::property_tree::ptree root; std::istringstream jsonStream(jsonString); try { boost::property_tree::read_json(jsonStream, root); } - catch (boost::property_tree::json_parser_error e) + catch (const boost::property_tree::json_parser_error &e) { mitkThrow() << "Could not parse json file. Error was:\n" << e.what(); } for (auto it : root) { if (it.second.empty()) { std::string propertyName = m_CESTPropertyPrefix + it.second.data(); if (m_JSONRevisionPropertyName == propertyName) { results->SetProperty(propertyName, mitk::StringProperty::New(it.first)); } else { results->SetProperty(propertyName, mitk::StringProperty::New(privateParameters[it.first])); } } else { MITK_ERROR << "Currently no support for nested dicom tag descriptors in json file."; } } std::string sampling = ""; std::string offset = ""; std::string measurements = ""; bool hasSamplingInformation = results->GetStringProperty("CEST.SamplingType", sampling); results->GetStringProperty("CEST.Offset", offset); results->GetStringProperty("CEST.measurements", measurements); if ("" == measurements) { std::string stringRepetitions = ""; std::string stringAverages = ""; results->GetStringProperty("CEST.repetitions", stringRepetitions); results->GetStringProperty("CEST.averages", stringAverages); std::stringstream measurementStream; try { measurementStream << std::stoi(stringRepetitions) + std::stoi(stringAverages); measurements = measurementStream.str(); MITK_INFO << "Could not find measurements, assuming repetitions + averages. Which is: " << measurements; } catch (const std::invalid_argument &ia) { MITK_ERROR << "Could not find measurements, fallback assumption of repetitions + averages could not be determined either: " << ia.what(); } } std::string preparationType = ""; std::string recoveryMode = ""; std::string spoilingType = ""; results->GetStringProperty("CEST.PreparationType", preparationType); results->GetStringProperty("CEST.RecoveryMode", recoveryMode); results->GetStringProperty("CEST.SpoilingType", spoilingType); if (this->IsT1Sequence(preparationType, recoveryMode, spoilingType, revisionString)) { MITK_INFO << "Parsed as T1 image"; mitk::LocaleSwitch localeSwitch("C"); std::stringstream trecStream; std::string trecPath = m_DicomDataPath + "/TREC.txt"; std::ifstream list(trecPath.c_str()); if (list.good()) { std::string currentTime; while (std::getline(list, currentTime)) { trecStream << currentTime << " "; } } else { MITK_WARN << "Assumed T1, but could not load TREC at " << trecPath; } results->SetStringProperty("CEST.TREC", trecStream.str().c_str()); } else { MITK_INFO << "Parsed as CEST or WASABI image"; } if (hasSamplingInformation) { std::string offsets = GetOffsetString(sampling, offset, measurements); results->SetStringProperty(m_OffsetsPropertyName.c_str(), offsets.c_str()); } else { MITK_WARN << "Could not determine sampling type."; } - + //persist all properties mitk::IPropertyPersistence *persSrv = GetPersistenceService(); if (persSrv) { auto propertyMap = results->GetMap(); for (auto const &prop : *propertyMap) { PropertyPersistenceInfo::Pointer info = PropertyPersistenceInfo::New(); std::string key = prop.first; std::replace(key.begin(), key.end(), '.', '_'); info->SetNameAndKey(prop.first, key); persSrv->AddInfo(info); } } return results; } mitk::PropertyList::Pointer mitk::CustomTagParser::ParseDicomProperty(mitk::TemporoSpatialStringProperty *dicomProperty) { if (!dicomProperty) { MITK_ERROR << "DICOM property empty"; } auto results = mitk::PropertyList::New(); if (dicomProperty) { results = ParseDicomPropertyString(dicomProperty->GetValue()); } return results; } std::vector mitk::CustomTagParser::GetInternalRevisions() { const std::vector configs = us::GetModuleContext()->GetModule()->FindResources("/", "*.json", false); std::vector availableRevisionsVector; for (auto const resource : configs) { availableRevisionsVector.push_back(std::stoi(resource.GetBaseName())); } return availableRevisionsVector; } std::vector mitk::CustomTagParser::GetExternalRevisions() { std::string stringToJSONDirectory = GetExternalJSONDirectory(); std::string prospectiveJsonsPath = stringToJSONDirectory + "/*.json"; std::set JsonFiles; Poco::Glob::glob(prospectiveJsonsPath, JsonFiles, Poco::Glob::GLOB_CASELESS); std::vector availableRevisionsVector; for (auto const jsonpath : JsonFiles) { std::string jsonDir; std::string jsonName; itksys::SystemTools::SplitProgramPath(jsonpath, jsonDir, jsonName); std::string revision = itksys::SystemTools::GetFilenameWithoutExtension(jsonName); // disregard jsons which contain letters in their name bool onlyNumbers = (revision.find_first_not_of("0123456789") == std::string::npos); if(onlyNumbers) { availableRevisionsVector.push_back(std::stoi(revision)); } } return availableRevisionsVector; } std::string mitk::CustomTagParser::GetClosestLowerRevision(std::string revisionString, std::vector availableRevisionsVector) { // descending order std::sort(availableRevisionsVector.begin(), availableRevisionsVector.end(), std::greater<>()); int revision = std::stoi(revisionString); int index = 0; int numberOfRevisions = availableRevisionsVector.size(); while (index < numberOfRevisions) { // current mapping still has a higher revision number if ((availableRevisionsVector[index] - revision) > 0) { ++index; } else { break; } } if (index < numberOfRevisions) { std::stringstream foundRevisionStream; foundRevisionStream << availableRevisionsVector[index]; return foundRevisionStream.str(); } return ""; } void mitk::CustomTagParser::GetClosestLowerRevision(std::string revisionString) { m_ClosestInternalRevision = GetClosestLowerRevision(revisionString, GetInternalRevisions()); m_ClosestExternalRevision = GetClosestLowerRevision(revisionString, GetExternalRevisions()); if ("Strict" == m_RevisionMappingStrategy && !((0 == m_ClosestInternalRevision.compare(revisionString)) || (0 == m_ClosestExternalRevision.compare(revisionString)))) { // strict revision mapping and neither revision does match the dicom meta data std::stringstream errorMessageStream; errorMessageStream << "\nCould not parse dicom data in strict mode, data revision " << revisionString << " has no known matching parameter mapping. To use the closest known older parameter mapping select the " << "\"Fuzzy\" revision mapping option when loading the data.\n" << "\nCurrently known revision mappings are:\n Precompiled:"; for (const auto revision : GetInternalRevisions()) { errorMessageStream << " " << revision; } errorMessageStream << "\n External:"; for (const auto revision : GetExternalRevisions()) { errorMessageStream << " " << revision; } errorMessageStream << "\n\nExternal revision mapping descriptions should be located at\n\n"; std::string stringToJSONDirectory = GetExternalJSONDirectory(); errorMessageStream << stringToJSONDirectory; errorMessageStream << "\n\nTo provide an external mapping for this revision create a " << revisionString << ".json there. You might need to create the directory first."; mitkThrow() << errorMessageStream.str(); } } std::string mitk::CustomTagParser::GetRevisionAppropriateJSONString(std::string revisionString) { std::string returnValue = ""; if ("" == revisionString) { MITK_WARN << "Could not extract revision"; } else { GetClosestLowerRevision(revisionString); bool useExternal = false; bool useInternal = false; if ("" != m_ClosestExternalRevision) { useExternal = true; } if ("" != m_ClosestInternalRevision) { useInternal = true; } if (useExternal && useInternal) { if (std::stoi(m_ClosestInternalRevision) > std::stoi(m_ClosestExternalRevision)) { useExternal = false; } } if (useExternal) { std::string stringToJSONDirectory = GetExternalJSONDirectory(); std::string prospectiveJsonPath = stringToJSONDirectory + "/" + m_ClosestExternalRevision + ".json"; std::ifstream externalJSON(prospectiveJsonPath.c_str()); if (externalJSON.good()) { MITK_INFO << "Found external json for CEST parameters at " << prospectiveJsonPath; std::stringstream buffer; buffer << externalJSON.rdbuf(); returnValue = buffer.str(); useInternal = false; } } if (useInternal) { std::string filename = m_ClosestInternalRevision + ".json"; us::ModuleResource jsonResource = us::GetModuleContext()->GetModule()->GetResource(filename); if (jsonResource.IsValid() && jsonResource.IsFile()) { MITK_INFO << "Found no external json for CEST parameters. Closest internal mapping is for revision " << m_ClosestInternalRevision; us::ModuleResourceStream jsonStream(jsonResource); std::stringstream buffer; buffer << jsonStream.rdbuf(); returnValue = buffer.str(); } } } if ("" == returnValue) { MITK_WARN << "Could not identify parameter mapping for the given revision " << revisionString << ", using default mapping."; returnValue = m_DefaultJsonString; } // inject the revision independent mapping before the first newline { returnValue.insert(returnValue.find("\n"), m_RevisionIndependentMapping); } return returnValue; } std::string mitk::CustomTagParser::GetOffsetString(std::string samplingType, std::string offset, std::string measurements) { mitk::LocaleSwitch localeSwitch("C"); std::stringstream results; std::string normalizationIndicatingOffset = "-300"; double offsetDouble = 0.0; int measurementsInt = 0; bool validOffset = false; bool validMeasurements = false; if ("" != offset) { validOffset = true; offsetDouble = std::stod(offset); } if ("" != measurements) { validMeasurements = true; measurementsInt = std::stoi(measurements); } std::vector offsetVector; if (validOffset && validMeasurements) { for (int step = 0; step < measurementsInt -1; ++step) { double currentOffset = -offsetDouble + 2 * step * offsetDouble / (measurementsInt - 2.0); offsetVector.push_back(currentOffset); } } else { MITK_WARN << "Invalid offset or measurements, offset calculation will only work for list sampling type."; } if (samplingType == "1" || samplingType == "Regular") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (const auto& entry : offsetVector) { results << entry << " "; } } } else if (samplingType == "2" || samplingType == "Alternating") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (auto& entry : offsetVector) { entry = std::abs(entry); } std::sort(offsetVector.begin(), offsetVector.end(), std::greater<>()); for (unsigned int index = 0; index < offsetVector.size(); ++index) { offsetVector[index] = std::pow(-1, index) * offsetVector[index]; } for (auto& entry : offsetVector) { results << entry << " "; } } } else if (samplingType == "3" || samplingType == "List") { std::string listPath = m_DicomDataPath + "/LIST.txt"; std::ifstream list(listPath.c_str()); if (list.good()) { std::string currentOffset; while (std::getline(list, currentOffset)) { results << currentOffset << " "; } } else { MITK_ERROR << "Could not load list at " << listPath; } } else if (samplingType == "4" || samplingType == "SingleOffset") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (int step = 0; step < measurementsInt - 1; ++step) { results << offsetDouble << " "; } } } else { MITK_WARN << "Encountered unknown sampling type."; } std::string resultString = results.str(); // replace multiple spaces by a single space std::string::iterator newEnditerator = std::unique(resultString.begin(), resultString.end(), [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } ); resultString.erase(newEnditerator, resultString.end()); if ((resultString.length() > 0) && (resultString.at(resultString.length() - 1) == ' ')) { resultString.erase(resultString.end() - 1, resultString.end()); } if ((resultString.length() > 0) && (resultString.at(0) == ' ')) { resultString.erase(resultString.begin(), ++(resultString.begin())); } return resultString; } void mitk::CustomTagParser::SetParseStrategy(std::string parseStrategy) { m_ParseStrategy = parseStrategy; } void mitk::CustomTagParser::SetRevisionMappingStrategy(std::string revisionMappingStrategy) { m_RevisionMappingStrategy = revisionMappingStrategy; } std::string mitk::CustomTagParser::GetExternalJSONDirectory() { std::string moduleLocation = us::GetModuleContext()->GetModule()->GetLocation(); std::string stringToModule; std::string libraryName; itksys::SystemTools::SplitProgramPath(moduleLocation, stringToModule, libraryName); std::stringstream jsonDirectory; jsonDirectory << stringToModule << "/CESTRevisionMapping"; return jsonDirectory.str(); } diff --git a/Modules/Classification/CLCore/src/mitkConfigurationHolder.cpp b/Modules/Classification/CLCore/src/mitkConfigurationHolder.cpp index 2bd98ff032..0112585583 100644 --- a/Modules/Classification/CLCore/src/mitkConfigurationHolder.cpp +++ b/Modules/Classification/CLCore/src/mitkConfigurationHolder.cpp @@ -1,312 +1,312 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include mitk::ConfigurationHolder::ConfigurationHolder() : m_ValueType(DT_UNINIZIALIZED) { m_GroupValue.clear(); } void mitk::ConfigurationHolder::SetBool(bool value) { m_BoolValue = value; m_ValueType = DT_BOOL; } void mitk::ConfigurationHolder::SetUnsignedInt(unsigned int value) { m_UIntValue = value; m_ValueType = DT_UINT; } void mitk::ConfigurationHolder::SetInt(int value) { m_IntValue = value; m_ValueType = DT_INT; } void mitk::ConfigurationHolder::SetDouble(double value) { m_DoubleValue = value; m_ValueType = DT_DOUBLE; } void mitk::ConfigurationHolder::SetString(std::string value) { m_StringValue = value; m_ValueType = DT_STRING; } void mitk::ConfigurationHolder::ClearGroup() { m_GroupValue.clear(); m_ValueType = DT_GROUP; } void mitk::ConfigurationHolder::AddToGroup(std::string id, const ConfigurationHolder &value) { m_GroupValue[id] = value; m_ValueType = DT_GROUP; } bool mitk::ConfigurationHolder::AsBool() { switch (m_ValueType) { case DT_UNINIZIALIZED: mitkThrow() << "No value stored"; break; case DT_BOOL: return m_BoolValue; break; case DT_UINT: return m_UIntValue; break; case DT_INT: return m_IntValue; break; case DT_DOUBLE: return (m_DoubleValue > 1 || m_DoubleValue < -1); break; case DT_STRING: return (m_StringValue != "0"); break; case DT_GROUP: mitkThrow() << "Cannot convert group data to bool"; break; default: mitkThrow() << "Unkown Data Type."; break; } } unsigned int mitk::ConfigurationHolder::AsUnsignedInt() { unsigned int result; std::istringstream ss(m_StringValue); ss >> result; switch (m_ValueType) { case DT_UNINIZIALIZED: mitkThrow() << "No value stored"; break; case DT_BOOL: return m_BoolValue; break; case DT_UINT: return m_UIntValue; break; case DT_INT: return m_IntValue; break; case DT_DOUBLE: return m_DoubleValue; break; case DT_STRING: return result; break; case DT_GROUP: mitkThrow() << "Cannot convert group data to bool"; break; default: mitkThrow() << "Unkown Data Type."; break; } } int mitk::ConfigurationHolder::AsInt() { int result; std::istringstream ss(m_StringValue); ss >> result; switch (m_ValueType) { case DT_UNINIZIALIZED: mitkThrow() << "No value stored"; break; case DT_BOOL: return m_BoolValue; break; case DT_UINT: return m_UIntValue; break; case DT_INT: return m_IntValue; break; case DT_DOUBLE: return m_DoubleValue; break; case DT_STRING: return result; break; case DT_GROUP: mitkThrow() << "Cannot convert group data to bool"; break; default: mitkThrow() << "Unkown Data Type."; break; } } double mitk::ConfigurationHolder::AsDouble() { double result; std::istringstream ss(m_StringValue); ss >> result; switch (m_ValueType) { case DT_UNINIZIALIZED: mitkThrow() << "No value stored"; break; case DT_BOOL: return m_BoolValue; break; case DT_UINT: return m_UIntValue; break; case DT_INT: return m_IntValue; break; case DT_DOUBLE: return m_DoubleValue > 1; break; case DT_STRING: return result; break; case DT_GROUP: mitkThrow() << "Cannot convert group data to bool"; break; default: mitkThrow() << "Unkown Data Type."; break; } } std::string mitk::ConfigurationHolder::AsString() { std::ostringstream strs; switch (m_ValueType) { case DT_UNINIZIALIZED: mitkThrow() << "No value stored"; break; case DT_BOOL: strs << m_BoolValue; break; case DT_UINT: strs << m_UIntValue; break; case DT_INT: strs << m_IntValue; break; case DT_DOUBLE: strs << m_DoubleValue; break; case DT_STRING: return m_StringValue; break; case DT_GROUP: mitkThrow() << "Cannot convert group data to bool"; break; default: mitkThrow() << "Unkown Data Type."; break; } return strs.str(); } std::vector mitk::ConfigurationHolder::AsStringVector() { if (m_ValueType != DT_GROUP) mitkThrow() << "No Group Data, cannot convert to String Vector"; std::vector result; for (auto iter = m_GroupValue.begin(); iter != m_GroupValue.end(); ++iter) { result.push_back((*iter).second.AsString()); } return result; } mitk::ConfigurationHolder& mitk::ConfigurationHolder::At(std::string id) { return m_GroupValue[id]; } bool mitk::ConfigurationHolder::AsBool(bool value) { try { return this->AsBool(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { return value; } } unsigned int mitk::ConfigurationHolder::AsUnsignedInt(unsigned int value) { try { return this->AsUnsignedInt(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { return value; } } int mitk::ConfigurationHolder::AsInt(int value) { try { return this->AsInt(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { return value; } } double mitk::ConfigurationHolder::AsDouble(double value) { try { return this->AsDouble(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { return value; } } std::string mitk::ConfigurationHolder::AsString(std::string value) { try { return this->AsString(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { return value; } -} \ No newline at end of file +} diff --git a/Modules/Core/TestingHelper/include/mitkTestingMacros.h b/Modules/Core/TestingHelper/include/mitkTestingMacros.h index 5427a407ad..add4e7e557 100644 --- a/Modules/Core/TestingHelper/include/mitkTestingMacros.h +++ b/Modules/Core/TestingHelper/include/mitkTestingMacros.h @@ -1,395 +1,395 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkTestingMacros_h #define mitkTestingMacros_h #include #include #include #include #include #include #include #include #include #include namespace mitk { /** @brief Indicate a failed test. */ class TestFailedException : public std::exception { public: TestFailedException() {} }; } /** * @brief Output some text without generating a terminating newline. Include * * @ingroup MITKTestingAPI */ #define MITK_TEST_OUTPUT_NO_ENDL(x) std::cout x; /** * @brief Output some text. * * @ingroup MITKTestingAPI */ #define MITK_TEST_OUTPUT(x) MITK_TEST_OUTPUT_NO_ENDL(x << "\n") /** * @brief Do some general test preparations. Must be called first in the * main test function. * * @deprecatedSince{2013_09} Use MITK_TEST_SUITE_REGISTRATION instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_BEGIN(testName) \ std::string mitkTestName(#testName); \ mitk::TestManager::GetInstance()->Initialize(); \ try \ { /** * @brief Fail and finish test with message MSG * * @deprecatedSince{2013_09} Use CPPUNIT_FAIL instead * @ingroup MITKTestingAPI */ #define MITK_TEST_FAILED_MSG(MSG) \ MITK_TEST_OUTPUT(MSG) \ throw mitk::TestFailedException(); /** * @brief Must be called last in the main test function. * * @deprecatedSince{2013_09} Use MITK_TEST_SUITE_REGISTRATION instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_END() \ } \ catch (const mitk::TestFailedException &) \ { \ MITK_TEST_OUTPUT(<< "Further test execution skipped.") \ mitk::TestManager::GetInstance()->TestFailed(); \ } \ catch (const std::exception &ex) \ { \ MITK_TEST_OUTPUT(<< "std::exception occured " << ex.what()) \ mitk::TestManager::GetInstance()->TestFailed(); \ } \ if (mitk::TestManager::GetInstance()->NumberOfFailedTests() > 0) \ { \ MITK_TEST_OUTPUT(<< mitkTestName << ": [DONE FAILED] , subtests passed: " \ << mitk::TestManager::GetInstance()->NumberOfPassedTests() \ << " failed: " \ << mitk::TestManager::GetInstance()->NumberOfFailedTests()) \ return EXIT_FAILURE; \ } \ else \ { \ MITK_TEST_OUTPUT(<< mitkTestName << ": " << mitk::TestManager::GetInstance()->NumberOfPassedTests() \ << " tests [DONE PASSED]") \ return EXIT_SUCCESS; \ } /** * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT or CPPUNIT_ASSERT_MESSAGE instead. */ #define MITK_TEST_CONDITION(COND, MSG) \ MITK_TEST_OUTPUT_NO_ENDL(<< MSG) \ if (!(COND)) \ { \ mitk::TestManager::GetInstance()->TestFailed(); \ MITK_TEST_OUTPUT(<< " [FAILED]\n" \ << "In " \ << __FILE__ \ << ", line " \ << __LINE__ \ << ": " #COND " : [FAILED]") \ } \ else \ { \ MITK_TEST_OUTPUT(<< " [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT or CPPUNIT_ASSERT_MESSAGE instead. */ #define MITK_TEST_CONDITION_REQUIRED(COND, MSG) \ MITK_TEST_OUTPUT_NO_ENDL(<< MSG) \ if (!(COND)) \ { \ MITK_TEST_FAILED_MSG(<< " [FAILED]\n" \ << " +--> in " \ << __FILE__ \ << ", line " \ << __LINE__ \ << ", expression is false: \"" #COND "\"") \ } \ else \ { \ MITK_TEST_OUTPUT(<< " [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * \brief Begin block which should be checked for exceptions * * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT_THROW instead. * @ingroup MITKTestingAPI * * This macro, together with MITK_TEST_FOR_EXCEPTION_END, can be used * to test whether a code block throws an expected exception. The test FAILS if the * exception is NOT thrown. A simple example: * MITK_TEST_FOR_EXCEPTION_BEGIN(itk::ImageFileReaderException) typedef itk::ImageFileReader< itk::Image > ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName("/tmp/not-existing"); reader->Update(); MITK_TEST_FOR_EXCEPTION_END(itk::ImageFileReaderException) * */ #define MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ try \ { /** * @deprecatedSince{2013_09} */ #define MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) \ mitk::TestManager::GetInstance()->TestFailed(); \ MITK_TEST_OUTPUT(<< "Expected an '" << #EXCEPTIONCLASS << "' exception. [FAILED]") \ } \ - catch (EXCEPTIONCLASS) \ + catch (const EXCEPTIONCLASS &) \ { \ MITK_TEST_OUTPUT(<< "Caught an expected '" << #EXCEPTIONCLASS << "' exception. [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * @brief Simplified version of MITK_TEST_FOR_EXCEPTION_BEGIN / END for * a single statement * * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT_THROW instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_FOR_EXCEPTION(EXCEPTIONCLASS, STATEMENT) \ MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ STATEMENT; \ MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) /** * @brief Testing macro to test if two objects are equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * Feel free to implement mitk::Equal for your own datatype or purpose. * * @param EXPECTED First object. * @param ACTUAL Second object. * @param MSG Message to appear with the test. * @throw Throws mitkException if a nullptr pointer is given as input. */ #define MITK_ASSERT_EQUAL(EXPECTED, ACTUAL, MSG) \ if (((EXPECTED).IsNull()) || ((ACTUAL).IsNull())) \ { \ mitkThrow() << "mitk::Equal does not work with nullptr pointer input."; \ } \ CPPUNIT_ASSERT_MESSAGE(MSG, mitk::Equal(*(EXPECTED), *(ACTUAL), mitk::eps, true)) /** * @brief Testing macro to test if two objects are not equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * * @deprecatedSince{2013_09} Use MITK_ASSERT_NOT_EQUAL instead. * * @param OBJ1 First object. * @param OBJ2 Second object. * @param MSG Message to appear with the test. * * \sa MITK_TEST_EQUAL */ #define MITK_TEST_NOT_EQUAL(OBJ1, OBJ2, MSG) \ CPPUNIT_ASSERT_MESSAGE(MSG, !mitk::Equal(*(OBJ1), *(OBJ2), mitk::eps, true)) /** * @brief Testing macro to test if two objects are not equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * * @param OBJ1 First object. * @param OBJ2 Second object. * @param MSG Message to appear with the test. * @throw Throws mitkException if a nullptr pointer is given as input. * * \sa MITK_ASSERT_EQUAL */ #define MITK_ASSERT_NOT_EQUAL(OBJ1, OBJ2, MSG) \ if (((OBJ1).IsNull()) || ((OBJ2).IsNull())) \ { \ mitkThrow() << "mitk::Equal does not work with nullptr pointer input."; \ } \ CPPUNIT_ASSERT_MESSAGE(MSG, !mitk::Equal(*(OBJ1), *(OBJ2), mitk::eps, true)) /** * @brief Registers the given test suite. * * @ingroup MITKTestingAPI * * @param TESTSUITE_NAME The name of the test suite class, without "TestSuite" * at the end. */ #define MITK_TEST_SUITE_REGISTRATION(TESTSUITE_NAME) \ int TESTSUITE_NAME##Test(int /*argc*/, char * /*argv*/ []) \ { \ int result = 0; \ try \ { \ CppUnit::TextUi::TestRunner runner; \ runner.addTest(TESTSUITE_NAME##TestSuite::suite()); \ result = runner.run() ? 0 : 1; \ } \ catch (const mitk::TestNotRunException& e) \ { \ MITK_WARN << "Test not run: " << e.GetDescription(); \ result = 77; \ } \ return result; \ } /** * @brief Adds a test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases. * The macro internally just calls the CPPUNIT_TEST macro. * * @param TESTMETHOD The name of the member funtion test. */ #define MITK_TEST(TESTMETHOD) CPPUNIT_TEST(TESTMETHOD) /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need custom parameters. * * @param TESTMETHOD The name of the member function test. * @param ARGS A std::vector object containing test parameter. * * @note Use the macro MITK_PARAMETERIZED_TEST only if you know what * you are doing. If you are not sure, use MITK_TEST instead. */ #define MITK_PARAMETERIZED_TEST(TESTMETHOD, ARGS) \ \ { \ std::string testName = #TESTMETHOD; \ for (std::size_t i = 0; i < ARGS.size(); ++i) \ { \ testName += "_" + ARGS[i]; \ } \ CPPUNIT_TEST_SUITE_ADD_TEST((new mitk::TestCaller( \ context.getTestNameFor(testName), &TestFixtureType::TESTMETHOD, context.makeFixture(), args))); \ } /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need parameters from the command line. * * @warning Use the macro MITK_PARAMETERIZED_CMD_LINE_TEST only * if you know what you are doing. If you are not sure, use * MITK_TEST instead. MITK_PARAMETERIZED_CMD_LINE_TEST is meant * for migrating from ctest to CppUnit. If you implement new * tests, the MITK_TEST macro will be sufficient. * * @param TESTMETHOD The name of the member function test. */ #define MITK_PARAMETERIZED_CMD_LINE_TEST(TESTMETHOD) \ CPPUNIT_TEST_SUITE_ADD_TEST((new mitk::TestCaller( \ context.getTestNameFor(#TESTMETHOD), &TestFixtureType::TESTMETHOD, context.makeFixture()))); /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need one custom parameter. * * @param TESTMETHOD The name of the member function test. * @param arg1 A custom string parameter being passed to the fixture. * * @note Use the macro MITK_PARAMETERIZED_TEST_1 only if you know what * you are doing. If you are not sure, use MITK_TEST instead. * * @see MITK_PARAMETERIZED_TEST */ #define MITK_PARAMETERIZED_TEST_1(TESTMETHOD, arg1) \ \ { \ std::vector args; \ args.push_back(arg1); \ MITK_PARAMETERIZED_TEST(TESTMETHOD, args) \ } /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need two custom parameter. * * @param TESTMETHOD The name of the member function test. * @param arg1 A custom string parameter being passed to the fixture. * * @note Use the macro MITK_PARAMETERIZED_TEST_2 only if you know what * you are doing. If you are not sure, use MITK_TEST instead. * * @see MITK_PARAMETERIZED_TEST */ #define MITK_PARAMETERIZED_TEST_2(TESTMETHOD, arg1, arg2) \ \ { \ std::vector args; \ args.push_back(arg1); \ args.push_back(arg2); \ MITK_PARAMETERIZED_TEST(TESTMETHOD, args) \ } #endif diff --git a/Modules/Core/src/DataManagement/mitkMaterial.cpp b/Modules/Core/src/DataManagement/mitkMaterial.cpp index 506e29ce46..ce5c37f3f7 100644 --- a/Modules/Core/src/DataManagement/mitkMaterial.cpp +++ b/Modules/Core/src/DataManagement/mitkMaterial.cpp @@ -1,380 +1,380 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMaterial.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include mitk::Material::Material(Color color, double opacity) { InitializeStandardValues(); SetColor(color); SetColorCoefficient(GetColorCoefficient()); SetSpecularColor(GetSpecularColor()); SetSpecularCoefficient(GetSpecularCoefficient()); SetSpecularPower(GetSpecularPower()); SetOpacity(opacity); SetInterpolation(GetInterpolation()); SetRepresentation(GetRepresentation()); SetLineWidth(GetLineWidth()); m_Name = ""; } mitk::Material::Material(double red, double green, double blue, double opacity) { InitializeStandardValues(); SetColor(red, green, blue); SetColorCoefficient(GetColorCoefficient()); SetSpecularColor(GetSpecularColor()); SetSpecularCoefficient(GetSpecularCoefficient()); SetSpecularPower(GetSpecularPower()); SetOpacity(opacity); SetInterpolation(GetInterpolation()); SetRepresentation(GetRepresentation()); SetLineWidth(GetLineWidth()); m_Name = ""; } mitk::Material::Material(double red, double green, double blue, double colorCoefficient, double specularCoefficient, double specularPower, double opacity) { InitializeStandardValues(); SetColor(red, green, blue); SetColorCoefficient(colorCoefficient); SetSpecularColor(GetSpecularColor()); SetSpecularCoefficient(specularCoefficient); SetSpecularPower(specularPower); SetOpacity(opacity); SetInterpolation(GetInterpolation()); SetRepresentation(GetRepresentation()); SetLineWidth(GetLineWidth()); m_Name = ""; } mitk::Material::Material(mitk::Material::Color color, double colorCoefficient, double specularCoefficient, double specularPower, double opacity) { InitializeStandardValues(); SetColor(color); SetColorCoefficient(colorCoefficient); SetSpecularColor(GetSpecularColor()); SetSpecularCoefficient(specularCoefficient); SetSpecularPower(specularPower); SetOpacity(opacity); SetInterpolation(GetInterpolation()); SetRepresentation(GetRepresentation()); SetLineWidth(GetLineWidth()); } mitk::Material::Material() { InitializeStandardValues(); SetColor(GetColor()); SetColorCoefficient(GetColorCoefficient()); SetSpecularColor(GetSpecularColor()); SetSpecularCoefficient(GetSpecularCoefficient()); SetSpecularPower(GetSpecularPower()); SetOpacity(GetOpacity()); SetInterpolation(GetInterpolation()); SetRepresentation(GetRepresentation()); SetLineWidth(GetLineWidth()); } mitk::Material::Material(const Material &property) : itk::Object() { Initialize(property); } mitk::Material::Material( const Material &property, double red, double green, double blue, double opacity, std::string name) { Initialize(property); SetColor(red, green, blue); SetOpacity(opacity); SetName(name); } bool mitk::Material::Assignable(const Material &other) const { try { const auto &otherinstance = dynamic_cast(other); // dear compiler, please don't optimize this away! Thanks. otherinstance.GetOpacity(); return true; } - catch (std::bad_cast) + catch (const std::bad_cast &) { } return false; } mitk::Material &mitk::Material::operator=(const mitk::Material &other) { try { const auto &otherProp(dynamic_cast(other)); Initialize(otherProp); } - catch (std::bad_cast) + catch (const std::bad_cast &) { // nothing to do then } return *this; } void mitk::Material::SetColor(mitk::Material::Color color) { m_Color = color; Modified(); } void mitk::Material::SetColor(double red, double green, double blue) { m_Color.Set(red, green, blue); Modified(); } void mitk::Material::SetColorCoefficient(double coefficient) { m_ColorCoefficient = coefficient; Modified(); } void mitk::Material::SetSpecularColor(mitk::Material::Color specularColor) { m_SpecularColor = specularColor; Modified(); } void mitk::Material::SetSpecularColor(double red, double green, double blue) { m_SpecularColor.Set(red, green, blue); Modified(); } void mitk::Material::SetSpecularCoefficient(double specularCoefficient) { m_SpecularCoefficient = specularCoefficient; Modified(); } void mitk::Material::SetSpecularPower(double specularPower) { m_SpecularPower = specularPower; Modified(); } void mitk::Material::SetOpacity(double opacity) { m_Opacity = opacity; Modified(); } void mitk::Material::SetInterpolation(InterpolationType interpolation) { m_Interpolation = interpolation; Modified(); } void mitk::Material::SetRepresentation(RepresentationType representation) { m_Representation = representation; Modified(); } void mitk::Material::SetLineWidth(float lineWidth) { m_LineWidth = lineWidth; Modified(); } mitk::Material::Color mitk::Material::GetColor() const { return m_Color; } double mitk::Material::GetColorCoefficient() const { return m_ColorCoefficient; } mitk::Material::Color mitk::Material::GetSpecularColor() const { return m_SpecularColor; } double mitk::Material::GetSpecularCoefficient() const { return m_SpecularCoefficient; } double mitk::Material::GetSpecularPower() const { return m_SpecularPower; } double mitk::Material::GetOpacity() const { return m_Opacity; } mitk::Material::InterpolationType mitk::Material::GetInterpolation() const { return m_Interpolation; } mitk::Material::RepresentationType mitk::Material::GetRepresentation() const { return m_Representation; } int mitk::Material::GetVtkInterpolation() const { switch (m_Interpolation) { case (Flat): return VTK_FLAT; case (Gouraud): return VTK_GOURAUD; case (Phong): return VTK_PHONG; } return VTK_GOURAUD; } int mitk::Material::GetVtkRepresentation() const { switch (m_Representation) { case (Points): return VTK_POINTS; case (Wireframe): return VTK_WIREFRAME; case (Surface): return VTK_SURFACE; } return VTK_SURFACE; } float mitk::Material::GetLineWidth() const { return m_LineWidth; } void mitk::Material::Initialize(const Material &property) { this->SetColor(property.GetColor()); this->SetColorCoefficient(property.GetColorCoefficient()); this->SetSpecularColor(property.GetSpecularColor()); this->SetSpecularCoefficient(property.GetSpecularCoefficient()); this->SetSpecularPower(property.GetSpecularPower()); this->SetOpacity(property.GetOpacity()); this->SetInterpolation(property.GetInterpolation()); this->SetRepresentation(property.GetRepresentation()); this->SetLineWidth(property.GetLineWidth()); this->SetName(property.GetName()); } bool mitk::Material::operator==(const Material &property) const { const auto *other = dynamic_cast(&property); if (other == nullptr) return false; else return (m_Color == other->GetColor() && m_ColorCoefficient == other->GetColorCoefficient() && m_SpecularColor == other->GetSpecularColor() && m_SpecularCoefficient == other->GetSpecularCoefficient() && m_SpecularPower == other->GetSpecularPower() && m_Opacity == other->GetOpacity() && m_Interpolation == other->GetInterpolation() && m_Name == other->GetName() && m_Representation == other->GetRepresentation() && m_LineWidth == other->GetLineWidth()); } void mitk::Material::InitializeStandardValues() { m_Color.Set(0.5, 0.5, 0.0); m_ColorCoefficient = 0.5; m_SpecularColor.Set(1.0, 1.0, 1.0); m_SpecularCoefficient = 0.5; m_SpecularPower = 10.0; m_Opacity = 1.0; m_Interpolation = Gouraud; m_Representation = Surface; m_LineWidth = 1.0; m_Name = ""; } void mitk::Material::Update() { this->SetColor(this->GetColor()); this->SetColorCoefficient(this->GetColorCoefficient()); this->SetSpecularColor(this->GetSpecularColor()); this->SetSpecularCoefficient(this->GetSpecularCoefficient()); this->SetSpecularPower(this->GetSpecularPower()); this->SetOpacity(this->GetOpacity()); this->SetInterpolation(this->GetInterpolation()); this->SetRepresentation(this->GetRepresentation()); } void mitk::Material::PrintSelf(std::ostream &os, itk::Indent /* unused */) const { os << "Name: " << GetName() << std::endl; os << "Color: " << GetColor() << std::endl; os << "ColorCoefficient" << GetColorCoefficient() << std::endl; os << "SpecularColor: " << GetSpecularColor() << std::endl; os << "SpecularCoefficient: " << GetSpecularCoefficient() << std::endl; os << "SpecularPower: " << GetSpecularPower() << std::endl; os << "Opacity: " << GetOpacity() << std::endl; os << "Line width: " << GetLineWidth() << std::endl; switch (GetInterpolation()) { case (Flat): os << "Interpolation: Flat" << std::endl; break; case (Gouraud): os << "Interpolation: Gouraud" << std::endl; break; case (Phong): os << "Interpolation: Phong" << std::endl; break; } switch (GetRepresentation()) { case (Points): os << "Representation: Points" << std::endl; break; case (Wireframe): os << "Representation: Wireframe" << std::endl; break; case (Surface): os << "Representation: Surface" << std::endl; break; } } diff --git a/Modules/Core/src/DataManagement/mitkPropertyDescriptions.cpp b/Modules/Core/src/DataManagement/mitkPropertyDescriptions.cpp index a2f49982ab..bafae1c07b 100644 --- a/Modules/Core/src/DataManagement/mitkPropertyDescriptions.cpp +++ b/Modules/Core/src/DataManagement/mitkPropertyDescriptions.cpp @@ -1,168 +1,168 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPropertyDescriptions.h" #include #include #include mitk::PropertyDescriptions::PropertyDescriptions() { } mitk::PropertyDescriptions::~PropertyDescriptions() { } bool mitk::PropertyDescriptions::AddDescription(const std::string &propertyName, const std::string &description, const std::string &className, bool overwrite) { if (propertyName.empty()) return false; DescriptionMap &descriptions = m_Descriptions[className]; std::pair ret = descriptions.insert(std::make_pair(propertyName, description)); if (!ret.second && overwrite) { ret.first->second = description; ret.second = true; } return ret.second; } bool mitk::PropertyDescriptions::AddDescriptionRegEx(const std::string &propertyRegEx, const std::string &description, const std::string &className, bool overwrite) { if (propertyRegEx.empty()) return false; try { std::regex checker(propertyRegEx); // no exception => valid we can change the info } - catch (std::regex_error) + catch (const std::regex_error &) { return false; } DescriptionMap &descriptions = m_DescriptionsRegEx[className]; std::pair ret = descriptions.insert(std::make_pair(propertyRegEx, description)); if (!ret.second && overwrite) { ret.first->second = description; ret.second = true; } return ret.second; } std::string mitk::PropertyDescriptions::GetDescription(const std::string &propertyName, const std::string &className, bool allowNameRegEx) const { if (!propertyName.empty()) { auto descriptionsIter = m_Descriptions.find(className); if (descriptionsIter != m_Descriptions.cend()) { auto iter = descriptionsIter->second.find(propertyName); if (iter != descriptionsIter->second.end()) return iter->second; } } if (allowNameRegEx && !propertyName.empty()) { auto selector = [propertyName](const DescriptionMap::value_type &x) { std::regex ex(x.first); return std::regex_match(propertyName, ex); }; auto descriptionsIter = m_DescriptionsRegEx.find(className); if (descriptionsIter != m_DescriptionsRegEx.cend()) { auto finding = std::find_if(descriptionsIter->second.cbegin(), descriptionsIter->second.cend(), selector); if (finding != descriptionsIter->second.cend()) return finding->second; } } return ""; } bool mitk::PropertyDescriptions::HasDescription(const std::string &propertyName, const std::string &className, bool allowNameRegEx) const { if (!propertyName.empty()) { auto descriptionsIter = m_Descriptions.find(className); if (descriptionsIter != m_Descriptions.cend()) { auto iter = descriptionsIter->second.find(propertyName); if (iter != descriptionsIter->second.end()) return true; } } if (allowNameRegEx && !propertyName.empty()) { auto selector = [propertyName](const DescriptionMap::value_type &x) { std::regex ex(x.first); return std::regex_match(propertyName, ex); }; auto descriptionsIter = m_DescriptionsRegEx.find(className); if (descriptionsIter != m_DescriptionsRegEx.cend()) { auto finding = std::find_if(descriptionsIter->second.cbegin(), descriptionsIter->second.cend(), selector); if (finding != descriptionsIter->second.cend()) return true; } } return false; } void mitk::PropertyDescriptions::RemoveAllDescriptions(const std::string &className) { m_Descriptions[className].clear(); m_DescriptionsRegEx[className].clear(); } void mitk::PropertyDescriptions::RemoveDescription(const std::string &propertyName, const std::string &className) { if (!propertyName.empty()) { m_Descriptions[className].erase(propertyName); m_DescriptionsRegEx[className].erase(propertyName); } } diff --git a/Modules/Core/test/mitkAccessByItkTest.cpp b/Modules/Core/test/mitkAccessByItkTest.cpp index 827366d8e3..295e115339 100644 --- a/Modules/Core/test/mitkAccessByItkTest.cpp +++ b/Modules/Core/test/mitkAccessByItkTest.cpp @@ -1,310 +1,310 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkTestingMacros.h" #include #include #define TestImageType(type, dim) \ MITK_TEST_CONDITION(typeid(type) == typeid(TPixel) && dim == VDimension, \ "Checking for correct type itk::Image<" #type "," #dim ">") #define TestVectorImageType(type, dim) \ MITK_TEST_CONDITION(typeid(type) == typeid(TPixel) && dim == VDimension && \ typeid(itk::VariableLengthVector) == typeid(typename ImageType::PixelType), \ "Checking for correct type itk::VectorImage<" #type "," #dim ">") class AccessByItkTest { public: typedef AccessByItkTest Self; typedef itk::Image IntImage2D; typedef itk::Image IntImage3D; typedef itk::Image FloatImage2D; typedef itk::Image FloatImage3D; typedef itk::VectorImage IntVectorImage3D; enum EImageType { Unknown = 0, Int2D, Int3D, Float2D, Float3D }; void testAccessByItk() { mitk::Image::Pointer mitkIntImage2D = createMitkImage(); mitk::Image::ConstPointer mitkIntImage3D(createMitkImage()); mitk::Image::ConstPointer mitkFloatImage2D(createMitkImage()); mitk::Image::Pointer mitkFloatImage3D = createMitkImage(); AccessByItk(mitkIntImage2D, AccessItkImage); AccessByItk(mitkIntImage3D, AccessItkImage); AccessByItk(mitkFloatImage2D, AccessItkImage); AccessByItk(mitkFloatImage3D, AccessItkImage); AccessByItk_n(mitkIntImage2D, AccessItkImage, (Int2D, 2)); AccessByItk_n(mitkIntImage3D, AccessItkImage, (Int3D, 2)); AccessByItk_n(mitkFloatImage2D, AccessItkImage, (Float2D, 2)); AccessByItk_n(mitkFloatImage3D, AccessItkImage, (Float3D, 2)); mitk::Image::Pointer mitkIntVectorImage3D = createMitkImage(2); // Test for wrong pixel type (the AccessByItk macro multi-plexes integral // types only by default) - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessByItk(mitkIntVectorImage3D, AccessItkImage); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) // Test for correct handling of vector images AccessVectorPixelTypeByItk(mitkIntVectorImage3D, AccessItkImage); AccessVectorPixelTypeByItk_n(mitkIntVectorImage3D, AccessItkImage, (Int3D, 2)); } void testAccessFixedDimensionByItk() { mitk::Image::Pointer mitkIntImage2D = createMitkImage(); mitk::Image::ConstPointer mitkIntImage3D(createMitkImage()); mitk::Image::ConstPointer mitkFloatImage2D(createMitkImage()); mitk::Image::Pointer mitkFloatImage3D = createMitkImage(); AccessFixedDimensionByItk(mitkIntImage2D, AccessItkImage, 2); AccessFixedDimensionByItk(mitkIntImage3D, AccessItkImage, 3); AccessFixedDimensionByItk(mitkFloatImage2D, AccessItkImage, 2); AccessFixedDimensionByItk(mitkFloatImage3D, AccessItkImage, 3); AccessFixedDimensionByItk_n(mitkIntImage2D, AccessItkImage, 2, (Int2D, 2)); AccessFixedDimensionByItk_n(mitkIntImage3D, AccessItkImage, 3, (Int3D, 2)); AccessFixedDimensionByItk_n(mitkFloatImage2D, AccessItkImage, 2, (Float2D, 2)); AccessFixedDimensionByItk_n(mitkFloatImage3D, AccessItkImage, 3, (Float3D, 2)); // Test for wrong dimension - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedDimensionByItk(mitkFloatImage3D, AccessItkImage, 2); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedDimensionByItk_n(mitkFloatImage3D, AccessItkImage, 2, (Float3D, 2)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) } void testAccessFixedPixelTypeByItk() { mitk::Image::Pointer mitkIntImage2D = createMitkImage(); mitk::Image::ConstPointer mitkIntImage3D(createMitkImage()); mitk::Image::ConstPointer mitkFloatImage2D(createMitkImage()); mitk::Image::Pointer mitkFloatImage3D = createMitkImage(); AccessFixedPixelTypeByItk(mitkIntImage2D, AccessItkImage, (int)(float)); AccessFixedPixelTypeByItk(mitkIntImage3D, AccessItkImage, (int)(float)); AccessFixedPixelTypeByItk(mitkFloatImage2D, AccessItkImage, (int)(float)); AccessFixedPixelTypeByItk(mitkFloatImage3D, AccessItkImage, (int)(float)); AccessFixedPixelTypeByItk_n(mitkIntImage2D, AccessItkImage, (int)(float), (Int2D, 2)); AccessFixedPixelTypeByItk_n(mitkIntImage3D, AccessItkImage, (int)(float), (Int3D, 2)); AccessFixedPixelTypeByItk_n(mitkFloatImage2D, AccessItkImage, (int)(float), (Float2D, 2)); AccessFixedPixelTypeByItk_n(mitkFloatImage3D, AccessItkImage, (int)(float), (Float3D, 2)); // Test for wrong pixel type - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedPixelTypeByItk(mitkFloatImage3D, AccessItkImage, (int)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedPixelTypeByItk_n(mitkFloatImage3D, AccessItkImage, (int), (Float3D, 2)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) } void testAccessFixedTypeByItk() { mitk::Image::Pointer mitkIntImage2D = createMitkImage(); mitk::Image::ConstPointer mitkIntImage3D(createMitkImage()); mitk::Image::ConstPointer mitkFloatImage2D(createMitkImage()); mitk::Image::Pointer mitkFloatImage3D = createMitkImage(); AccessFixedTypeByItk(mitkIntImage2D, AccessItkImage, (int)(float), (2)(3)); AccessFixedTypeByItk(mitkIntImage3D, AccessItkImage, (int)(float), (2)(3)); AccessFixedTypeByItk(mitkFloatImage2D, AccessItkImage, (int)(float), (2)(3)); AccessFixedTypeByItk(mitkFloatImage3D, AccessItkImage, (int)(float), (2)(3)); AccessFixedTypeByItk_n(mitkIntImage2D, AccessItkImage, (int)(float), (2)(3), (Int2D, 2)); AccessFixedTypeByItk_n(mitkIntImage3D, AccessItkImage, (int)(float), (2)(3), (Int3D, 2)); AccessFixedTypeByItk_n(mitkFloatImage2D, AccessItkImage, (int)(float), (2)(3), (Float2D, 2)); AccessFixedTypeByItk_n(mitkFloatImage3D, AccessItkImage, (int)(float), (2)(3), (Float3D, 2)); // Test for wrong dimension - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedTypeByItk(mitkFloatImage3D, AccessItkImage, (float), (2)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedTypeByItk_n(mitkFloatImage3D, AccessItkImage, (float), (2), (Float3D, 2)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) // Test for wrong pixel type - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedTypeByItk(mitkFloatImage3D, AccessItkImage, (int), (3)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) - MITK_TEST_FOR_EXCEPTION_BEGIN(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::AccessByItkException) AccessFixedTypeByItk_n(mitkFloatImage3D, AccessItkImage, (int), (3), (Float3D, 2)); - MITK_TEST_FOR_EXCEPTION_END(const mitk::AccessByItkException &) + MITK_TEST_FOR_EXCEPTION_END(mitk::AccessByItkException) } void testAccessTwoImagesFixedDimensionByItk() { mitk::Image::Pointer mitkIntImage2D = createMitkImage(); mitk::Image::ConstPointer mitkFloatImage2D(createMitkImage()); AccessTwoImagesFixedDimensionByItk(mitkIntImage2D, mitkFloatImage2D, AccessTwoItkImages, 2); } template void AccessItkImage(const itk::Image *, EImageType param1 = Unknown, int param2 = 0, int param3 = 0) { switch (param1) { case Int2D: TestImageType(int, 2) break; case Int3D: TestImageType(int, 3) break; case Float2D: TestImageType(float, 2) break; case Float3D: TestImageType(float, 3) break; default: break; } if (param2) { MITK_TEST_CONDITION(param2 == 2, "Checking for correct second parameter") } if (param3) { MITK_TEST_CONDITION(param3 == 3, "Checking for correct third parameter") } } template void AccessItkImage(itk::VectorImage *, EImageType param1 = Unknown, int param2 = 0, int param3 = 0) { typedef itk::VectorImage ImageType; switch (param1) { case Int2D: TestVectorImageType(int, 2) break; case Int3D: TestVectorImageType(int, 3) break; case Float2D: TestVectorImageType(float, 2) break; case Float3D: TestVectorImageType(float, 3) break; default: break; } if (param2) { MITK_TEST_CONDITION(param2 == 2, "Checking for correct second parameter") } if (param3) { MITK_TEST_CONDITION(param3 == 3, "Checking for correct third parameter") } } private: template void AccessTwoItkImages(itk::Image * /*itkImage1*/, itk::Image * /*itkImage2*/) { if (!(typeid(int) == typeid(TPixel1) && typeid(float) == typeid(TPixel2) && VDimension1 == 2 && VDimension2 == 2)) { throw std::runtime_error("Image type mismatch"); } } template mitk::Image::Pointer createMitkImage() { typename ImageType::Pointer itkImage = ImageType::New(); typename ImageType::IndexType start; start.Fill(0); typename ImageType::SizeType size; size.Fill(3); typename ImageType::RegionType region; region.SetSize(size); region.SetIndex(start); itkImage->SetRegions(region); itkImage->Allocate(); return mitk::GrabItkImageMemory(itkImage); } template mitk::Image::Pointer createMitkImage(std::size_t vectorLength) { typename ImageType::Pointer itkImage = ImageType::New(); typename ImageType::IndexType start; start.Fill(0); typename ImageType::SizeType size; size.Fill(3); typename ImageType::RegionType region; region.SetSize(size); region.SetIndex(start); itkImage->SetRegions(region); itkImage->SetVectorLength(vectorLength); itkImage->Allocate(); return mitk::GrabItkImageMemory(itkImage); } }; int mitkAccessByItkTest(int /*argc*/, char * /*argv*/ []) { MITK_TEST_BEGIN("AccessByItk") AccessByItkTest accessTest; MITK_TEST_OUTPUT(<< "Testing AccessByItk macro") accessTest.testAccessByItk(); MITK_TEST_OUTPUT(<< "Testing AccessFixedDimensionByItk macro") accessTest.testAccessFixedDimensionByItk(); MITK_TEST_OUTPUT(<< "Testing AccessFixedTypeByItk macro") accessTest.testAccessFixedTypeByItk(); MITK_TEST_OUTPUT(<< "Testing AccessFixedPixelTypeByItk macro") accessTest.testAccessFixedPixelTypeByItk(); MITK_TEST_OUTPUT(<< "Testing AccessTwoImagesFixedDimensionByItk macro") accessTest.testAccessTwoImagesFixedDimensionByItk(); MITK_TEST_END() } diff --git a/Modules/Core/test/mitkDataStorageTest.cpp b/Modules/Core/test/mitkDataStorageTest.cpp index a76907f313..815dcd668c 100644 --- a/Modules/Core/test/mitkDataStorageTest.cpp +++ b/Modules/Core/test/mitkDataStorageTest.cpp @@ -1,878 +1,878 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkColorProperty.h" #include "mitkDataNode.h" #include "mitkGroupTagProperty.h" #include "mitkImage.h" #include "mitkReferenceCountWatcher.h" #include "mitkStringProperty.h" #include "mitkSurface.h" #include "mitkDataStorage.h" #include "mitkIOUtil.h" #include "mitkMessage.h" #include "mitkNodePredicateAnd.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateDimension.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateOr.h" #include "mitkNodePredicateProperty.h" #include "mitkNodePredicateSource.h" #include "mitkStandaloneDataStorage.h" //#include "mitkPicFileReader.h" #include "mitkTestingMacros.h" void TestDataStorage(mitk::DataStorage *ds, std::string filename); namespace mitk { class TestStandaloneDataStorage : public StandaloneDataStorage { public: mitkClassMacro(TestStandaloneDataStorage, mitk::DataStorage); itkFactorylessNewMacro(Self) itkCloneMacro(Self) std::map GetModifiedObserverTags() const { return m_NodeModifiedObserverTags; } std::map GetDeletedObserverTags() const { return m_NodeDeleteObserverTags; } protected: TestStandaloneDataStorage() {} }; } class DSEventReceiver // Helper class for event testing { public: const mitk::DataNode *m_NodeAdded; const mitk::DataNode *m_NodeRemoved; DSEventReceiver() : m_NodeAdded(nullptr), m_NodeRemoved(nullptr) {} void OnAdd(const mitk::DataNode *node) { m_NodeAdded = node; } void OnRemove(const mitk::DataNode *node) { m_NodeRemoved = node; } }; /// /// \brief a class for checking if the datastorage is really thread safe /// /// Therefore it listens to a node contained in the datastorage. when this node /// gets removed and deleted, this class gets informed by calling OnObjectDelete(). /// in OnObjectDelete() an empty node gets added. this must not cause a deadlock /// struct ItkDeleteEventListener { ItkDeleteEventListener(mitk::DataStorage *ds) : m_Node(nullptr), m_DataStorage(ds), m_DeleteObserverTag(0) {} void SetNode(mitk::DataNode *_Node) { if (m_Node) return; m_Node = _Node; itk::MemberCommand::Pointer onObjectDelete = itk::MemberCommand::New(); onObjectDelete->SetCallbackFunction(this, &ItkDeleteEventListener::OnObjectDelete); m_DeleteObserverTag = m_Node->AddObserver(itk::DeleteEvent(), onObjectDelete); } void OnObjectDelete(const itk::Object * /*caller*/, const itk::EventObject &) { mitk::DataNode::Pointer node = mitk::DataNode::New(); m_DataStorage->Add(node); // SHOULD NOT CAUSE A DEADLOCK! m_DataStorage->Remove(node); // tidy up: remove the empty node again m_Node = nullptr; } protected: mitk::DataNode *m_Node; mitk::DataStorage::Pointer m_DataStorage; unsigned int m_DeleteObserverTag; }; //## Documentation //## main testing method //## NOTE: the current Singleton implementation of DataTreeStorage will lead to crashes if a testcase fails //## and therefore mitk::DataStorage::ShutdownSingleton() is not called. int mitkDataStorageTest(int argc, char *argv[]) { MITK_TEST_BEGIN("DataStorageTest"); // muellerm: test observer tag remove mitk::TestStandaloneDataStorage::Pointer testDS = mitk::TestStandaloneDataStorage::New(); mitk::DataNode::Pointer n1 = mitk::DataNode::New(); testDS->Add(n1); MITK_TEST_CONDITION_REQUIRED(testDS->GetModifiedObserverTags().size() == 1, "Testing if modified" " observer was added."); MITK_TEST_CONDITION_REQUIRED(testDS->GetDeletedObserverTags().size() == 1, "Testing if delete" " observer was added."); testDS->Remove(n1); MITK_TEST_CONDITION_REQUIRED(testDS->GetModifiedObserverTags().size() == 0, "Testing if modified" " observer was removed."); MITK_TEST_CONDITION_REQUIRED(testDS->GetDeletedObserverTags().size() == 0, "Testing if delete" " observer was removed."); /* Create StandaloneDataStorage */ MITK_TEST_OUTPUT(<< "Create StandaloneDataStorage : "); mitk::StandaloneDataStorage::Pointer sds; try { sds = mitk::StandaloneDataStorage::New(); MITK_TEST_CONDITION_REQUIRED(sds.IsNotNull(), "Testing Instatiation"); } catch (...) { MITK_TEST_FAILED_MSG(<< "Exception during creation of StandaloneDataStorage"); } MITK_TEST_OUTPUT(<< "Testing StandaloneDataStorage: "); MITK_TEST_CONDITION_REQUIRED(argc > 1, "Testing correct test invocation"); TestDataStorage(sds, argv[1]); // TODO: Add specific StandaloneDataStorage Tests here sds = nullptr; MITK_TEST_END(); } //##Documentation //## @brief Test for the DataStorage class and its associated classes (e.g. the predicate classes) //## This method will be called once for each subclass of DataStorage void TestDataStorage(mitk::DataStorage *ds, std::string filename) { /* DataStorage valid? */ MITK_TEST_CONDITION_REQUIRED(ds != nullptr, "DataStorage valid?"); // Take the ItkImageFile Reader for the .nrrd data format. // (was previously pic which is now deprecated format) mitk::Image::Pointer image = mitk::IOUtil::Load(filename); // create some DataNodes to fill the ds mitk::DataNode::Pointer n1 = mitk::DataNode::New(); // node with image and name property // mitk::Image::Pointer image = mitk::Image::New(); // unsigned int imageDimensions[] = { 10, 10, 10, 10 }; // mitk::PixelType pt(typeid(int)); // image->Initialize( pt, 4, imageDimensions ); n1->SetData(image); n1->SetProperty("name", mitk::StringProperty::New("Node 1 - Image Node")); mitk::DataStorage::SetOfObjects::Pointer parents1 = mitk::DataStorage::SetOfObjects::New(); mitk::DataNode::Pointer n2 = mitk::DataNode::New(); // node with surface and name and color properties mitk::Surface::Pointer surface = mitk::Surface::New(); n2->SetData(surface); n2->SetProperty("name", mitk::StringProperty::New("Node 2 - Surface Node")); mitk::Color color; color.Set(1.0f, 1.0f, 0.0f); n2->SetColor(color); n2->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New()); mitk::DataStorage::SetOfObjects::Pointer parents2 = mitk::DataStorage::SetOfObjects::New(); parents2->InsertElement(0, n1); // n1 (image node) is source of n2 (surface node) mitk::DataNode::Pointer n3 = mitk::DataNode::New(); // node without data but with name property n3->SetProperty("name", mitk::StringProperty::New("Node 3 - Empty Node")); n3->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New()); n3->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New()); mitk::DataStorage::SetOfObjects::Pointer parents3 = mitk::DataStorage::SetOfObjects::New(); parents3->InsertElement(0, n2); // n2 is source of n3 mitk::DataNode::Pointer n4 = mitk::DataNode::New(); // node without data but with color property n4->SetColor(color); n4->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New()); mitk::DataStorage::SetOfObjects::Pointer parents4 = mitk::DataStorage::SetOfObjects::New(); parents4->InsertElement(0, n2); parents4->InsertElement(1, n3); // n2 and n3 are sources of n4 mitk::DataNode::Pointer n5 = mitk::DataNode::New(); // extra node n5->SetProperty("name", mitk::StringProperty::New("Node 5")); try /* adding objects */ { /* Add an object */ ds->Add(n1, parents1); MITK_TEST_CONDITION_REQUIRED((ds->GetAll()->Size() == 1) && (ds->GetAll()->GetElement(0) == n1), "Testing Adding a new object"); /* Check exception on adding the same object again */ MITK_TEST_OUTPUT(<< "Check exception on adding the same object again: "); - MITK_TEST_FOR_EXCEPTION(..., ds->Add(n1, parents1)); + MITK_TEST_FOR_EXCEPTION(std::exception, ds->Add(n1, parents1)); MITK_TEST_CONDITION(ds->GetAll()->Size() == 1, "Test if object count is correct after exception"); /* Add an object that has a source object */ ds->Add(n2, parents2); MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 2, "Testing Adding an object that has a source object"); /* Add some more objects needed for further tests */ ds->Add(n3, parents3); // n3 object that has name property and one parent ds->Add(n4, parents4); // n4 object that has color property ds->Add(n5); // n5 has no parents MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 5, "Adding some more objects needed for further tests"); } catch (...) { MITK_TEST_FAILED_MSG(<< "Exeption during object creation"); } try /* object retrieval methods */ { /* Requesting all Objects */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetAll(); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((stlAll.size() == 5) // check if all tree nodes are in resultset && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()), "Testing GetAll()"); } /* Requesting a named object */ { mitk::NodePredicateProperty::Pointer predicate( mitk::NodePredicateProperty::New("name", mitk::StringProperty::New("Node 2 - Surface Node"))); mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2), "Requesting a named object"); } /* Requesting objects of specific data type */ { mitk::NodePredicateDataType::Pointer predicate(mitk::NodePredicateDataType::New("Image")); mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific data type") } /* Requesting objects of specific dimension */ { mitk::NodePredicateDimension::Pointer predicate(mitk::NodePredicateDimension::New(4)); mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific dimension") } /* Requesting objects with specific data object */ { mitk::NodePredicateData::Pointer predicate(mitk::NodePredicateData::New(image)); mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects with specific data object") } /* Requesting objects with nullptr data */ { mitk::NodePredicateData::Pointer predicate(mitk::NodePredicateData::New(nullptr)); mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 3) && (std::find(all->begin(), all->end(), n3) != all->end()) && (std::find(all->begin(), all->end(), n4) != all->end()) && (std::find(all->begin(), all->end(), n5) != all->end()), "Requesting objects with nullptr data"); } /* Requesting objects that meet a conjunction criteria */ { mitk::NodePredicateDataType::Pointer p1 = mitk::NodePredicateDataType::New("Surface"); mitk::NodePredicateProperty::Pointer p2 = mitk::NodePredicateProperty::New("color", mitk::ColorProperty::New(color)); mitk::NodePredicateAnd::Pointer predicate = mitk::NodePredicateAnd::New(); predicate->AddPredicate(p1); predicate->AddPredicate(p2); // objects must be of datatype "Surface" and have red color (= n2) const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2), "Requesting objects that meet a conjunction criteria"); } /* Requesting objects that meet a disjunction criteria */ { mitk::NodePredicateDataType::Pointer p1(mitk::NodePredicateDataType::New("Image")); mitk::NodePredicateProperty::Pointer p2( mitk::NodePredicateProperty::New("color", mitk::ColorProperty::New(color))); mitk::NodePredicateOr::Pointer predicate = mitk::NodePredicateOr::New(); predicate->AddPredicate(p1); predicate->AddPredicate(p2); // objects must be of datatype "Surface" or have red color (= n1, n2, n4) const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); MITK_TEST_CONDITION((all->Size() == 3) && (std::find(all->begin(), all->end(), n1) != all->end()) && (std::find(all->begin(), all->end(), n2) != all->end()) && (std::find(all->begin(), all->end(), n4) != all->end()), "Requesting objects that meet a disjunction criteria"); } /* Requesting objects that do not meet a criteria */ { mitk::ColorProperty::Pointer cp = mitk::ColorProperty::New(color); mitk::NodePredicateProperty::Pointer proppred(mitk::NodePredicateProperty::New("color", cp)); mitk::NodePredicateNot::Pointer predicate(mitk::NodePredicateNot::New(proppred)); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 3) // check if correct objects are in resultset && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()), "Requesting objects that do not meet a criteria"); } /* Requesting *direct* source objects */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n3, nullptr, true); // Get direct parents of n3 (=n2) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 1) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()), "Requesting *direct* source objects"); } /* Requesting *all* source objects */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n3, nullptr, false); // Get all parents of n3 (= n1 + n2) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 2) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()), "Requesting *all* source objects"); // check if n1 and n2 are the resultset } /* Requesting *all* sources of object with multiple parents */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, nullptr, false); // Get all parents of n4 (= n1 + n2 + n3) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION( (all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset , "Requesting *all* sources of object with multiple parents"); } /* Requesting *direct* derived objects */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, nullptr, true); // Get direct childs of n1 (=n2) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 1) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) // check if n1 is the resultset , "Requesting *direct* derived objects"); } ///* Requesting *direct* derived objects with multiple parents/derivations */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n2, nullptr, true); // Get direct childs of n2 (=n3 + n4) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION( (all->Size() == 2) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n3 is the resultset && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()) // check if n4 is the resultset , "Requesting *direct* derived objects with multiple parents/derivations"); } //* Requesting *all* derived objects */ { const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, nullptr, false); // Get all childs of n1 (=n2, n3, n4) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()), "Requesting *all* derived objects"); } /* Checking for circular source relationships */ { parents1->InsertElement(0, n4); // make n1 derived from n4 (which is derived from n2, which is derived from n1) const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources( n4, nullptr, false); // Get all parents of n4 (= n1 + n2 + n3, not n4 itself and not multiple versions of the nodes!) std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION( (all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset , "Checking for circular source relationships"); } ///* Checking for circular derivation relationships can not be performed, because the internal derivations /// datastructure // can not be accessed from the outside. (Therefore it should not be possible to create these circular relations // */ //* Checking GroupTagProperty */ { mitk::GroupTagProperty::Pointer tp = mitk::GroupTagProperty::New(); mitk::NodePredicateProperty::Pointer pred(mitk::NodePredicateProperty::New("Resection Proposal 1", tp)); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(pred); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 2) // check if n2 and n3 are in resultset && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()), "Checking GroupTagProperty"); } /* Checking GroupTagProperty 2 */ { mitk::GroupTagProperty::Pointer tp = mitk::GroupTagProperty::New(); mitk::NodePredicateProperty::Pointer pred(mitk::NodePredicateProperty::New("Resection Proposal 2", tp)); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(pred); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 2) // check if n3 and n4 are in resultset && (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()), "Checking GroupTagProperty 2"); } /* Checking direct sources with condition */ { mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("Surface"); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, true); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 1) // check if n2 is in resultset && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()), "checking direct sources with condition"); } /* Checking all sources with condition */ { mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("Image"); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 1) // check if n1 is in resultset && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()), "Checking all sources with condition"); } /* Checking all sources with condition with empty resultset */ { mitk::NodePredicateDataType::Pointer pred = mitk::NodePredicateDataType::New("VesselTree"); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false); MITK_TEST_CONDITION(all->Size() == 0, "Checking all sources with condition with empty resultset"); // check if resultset is empty } /* Checking direct derivations with condition */ { mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("color"); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, true); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 1) // check if n2 is in resultset && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()), "Checking direct derivations with condition"); } /* Checking all derivations with condition */ { mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("color"); const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, false); std::vector stlAll = all->CastToSTLConstContainer(); MITK_TEST_CONDITION((all->Size() == 2) // check if n2 and n4 are in resultset && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) && (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()), "Checking direct derivations with condition"); } /* Checking named node method */ MITK_TEST_CONDITION(ds->GetNamedNode("Node 2 - Surface Node") == n2, "Checking named node method"); MITK_TEST_CONDITION(ds->GetNamedNode(std::string("Node 2 - Surface Node")) == n2, "Checking named node(std::string) method"); /* Checking named node method with wrong name */ MITK_TEST_CONDITION(ds->GetNamedNode("This name does not exist") == nullptr, "Checking named node method with wrong name"); /* Checking named object method */ MITK_TEST_CONDITION(ds->GetNamedObject("Node 1 - Image Node") == image, "Checking named object method"); MITK_TEST_CONDITION(ds->GetNamedObject(std::string("Node 1 - Image Node")) == image, "Checking named object(std::string) method"); /* Checking named object method with wrong DataType */ MITK_TEST_CONDITION(ds->GetNamedObject("Node 1 - Image Node") == nullptr, "Checking named object method with wrong DataType"); /* Checking named object method with wrong name */ MITK_TEST_CONDITION(ds->GetNamedObject("This name does not exist") == nullptr, "Checking named object method with wrong name"); /* Checking GetNamedDerivedNode with valid name and direct derivation only */ MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 2 - Surface Node", n1, true) == n2, "Checking GetNamedDerivedNode with valid name & direct derivation only"); /* Checking GetNamedDerivedNode with invalid Name and direct derivation only */ MITK_TEST_CONDITION(ds->GetNamedDerivedNode("wrong name", n1, true) == nullptr, "Checking GetNamedDerivedNode with invalid name & direct derivation only"); /* Checking GetNamedDerivedNode with invalid Name and direct derivation only */ MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, false) == n3, "Checking GetNamedDerivedNode with invalid name & direct derivation only"); /* Checking GetNamedDerivedNode with valid Name but direct derivation only */ MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, true) == nullptr, "Checking GetNamedDerivedNode with valid Name but direct derivation only"); /* Checking GetNode with valid predicate */ { mitk::NodePredicateDataType::Pointer p(mitk::NodePredicateDataType::New("Image")); MITK_TEST_CONDITION(ds->GetNode(p) == n1, "Checking GetNode with valid predicate"); } /* Checking GetNode with invalid predicate */ { mitk::NodePredicateDataType::Pointer p(mitk::NodePredicateDataType::New("PointSet")); MITK_TEST_CONDITION(ds->GetNode(p) == nullptr, "Checking GetNode with invalid predicate"); } } // object retrieval methods catch (...) { MITK_TEST_FAILED_MSG(<< "Exeption during object retrieval (GetXXX() Methods)"); } try /* object removal methods */ { /* Checking removal of a node without relations */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); int refCountbeforeDS = watcher->GetReferenceCount(); ds->Add(extra); MITK_TEST_CONDITION(ds->GetNamedNode("extra") == extra, "Adding extra node"); ds->Remove(extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == nullptr) && (refCountbeforeDS == watcher->GetReferenceCount()), "Checking removal of a node without relations"); extra = nullptr; } /* Checking removal of a node with a parent */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); int refCountbeforeDS = watcher->GetReferenceCount(); ds->Add(extra, n1); // n1 is parent of extra MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1 , "Adding extra node"); ds->Remove(extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == nullptr) && (refCountbeforeDS == watcher->GetReferenceCount()) && (ds->GetDerivations(n1)->Size() == 1), "Checking removal of a node with a parent"); extra = nullptr; } /* Checking removal of a node with two parents */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); int refCountbeforeDS = watcher->GetReferenceCount(); mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New(); p->push_back(n1); p->push_back(n2); ds->Add(extra, p); // n1 and n2 are parents of extra MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1 && (ds->GetDerivations(n2)->Size() == 3), "add extra node"); ds->Remove(extra); MITK_TEST_CONDITION( (ds->GetNamedNode("extra") == nullptr) && (refCountbeforeDS == watcher->GetReferenceCount()) && (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1 && (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2 , "Checking removal of a node with two parents"); extra = nullptr; } /* Checking removal of a node with two derived nodes */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); int refCountbeforeDS = watcher->GetReferenceCount(); ds->Add(extra); mitk::DataNode::Pointer d1 = mitk::DataNode::New(); d1->SetProperty("name", mitk::StringProperty::New("d1")); ds->Add(d1, extra); mitk::DataNode::Pointer d2 = mitk::DataNode::New(); d2->SetProperty("name", mitk::StringProperty::New("d2")); ds->Add(d2, extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1") == d1) && (ds->GetNamedNode("d2") == d2) && (ds->GetSources(d1)->Size() == 1) // extra should be source of d1 && (ds->GetSources(d2)->Size() == 1) // extra should be source of d2 && (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra , "add extra node"); ds->Remove(extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == nullptr) && (ds->GetNamedNode("d1") == d1) && (ds->GetNamedNode("d2") == d2) && (refCountbeforeDS == watcher->GetReferenceCount()) && (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore && (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore , "Checking removal of a node with two derived nodes"); extra = nullptr; } /* Checking removal of a node with two parents and two derived nodes */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); mitk::ReferenceCountWatcher::Pointer n1watcher = new mitk::ReferenceCountWatcher(n1); int refCountbeforeDS = watcher->GetReferenceCount(); mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New(); p->push_back(n1); p->push_back(n2); ds->Add(extra, p); // n1 and n2 are parents of extra mitk::DataNode::Pointer d1 = mitk::DataNode::New(); d1->SetProperty("name", mitk::StringProperty::New("d1x")); ds->Add(d1, extra); mitk::DataNode::Pointer d2 = mitk::DataNode::New(); d2->SetProperty("name", mitk::StringProperty::New("d2x")); ds->Add(d2, extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1x") == d1) && (ds->GetNamedNode("d2x") == d2) && (ds->GetSources(d1)->Size() == 1) // extra should be source of d1 && (ds->GetSources(d2)->Size() == 1) // extra should be source of d2 && (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1 && (ds->GetDerivations(n2)->Size() == 3) // n3, n4 and extra should be derived from n2 && (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra , "add extra node"); ds->Remove(extra); MITK_TEST_CONDITION( (ds->GetNamedNode("extra") == nullptr) && (ds->GetNamedNode("d1x") == d1) && (ds->GetNamedNode("d2x") == d2) && (refCountbeforeDS == watcher->GetReferenceCount()) && (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1 && (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2 && (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore && (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore , "Checking removal of a node with two parents and two derived nodes"); extra = nullptr; } } catch (...) { MITK_TEST_FAILED_MSG(<< "Exeption during object removal methods"); } /* Checking for node is it's own parent exception */ { - MITK_TEST_FOR_EXCEPTION_BEGIN(...); + MITK_TEST_FOR_EXCEPTION_BEGIN(std::exception); mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New(); p->push_back(n1); p->push_back(extra); // extra is parent of extra!!! ds->Add(extra, p); - MITK_TEST_FOR_EXCEPTION_END(...); + MITK_TEST_FOR_EXCEPTION_END(std::exception); } /* Checking reference count of node after add and remove */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); extra->SetProperty("name", mitk::StringProperty::New("extra")); mitk::DataStorage::SetOfObjects::Pointer p = mitk::DataStorage::SetOfObjects::New(); p->push_back(n1); p->push_back(n3); ds->Add(extra, p); extra = nullptr; ds->Remove(ds->GetNamedNode("extra")); MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Checking reference count of node after add and remove"); } /* Checking removal of a node with two derived nodes [ dataStorage->GetDerivations( rootNode )] see bug #3426 */ { mitk::DataNode::Pointer extra = mitk::DataNode::New(); extra->SetProperty("name", mitk::StringProperty::New("extra")); ds->Add(extra); mitk::DataNode::Pointer d1y = mitk::DataNode::New(); d1y->SetProperty("name", mitk::StringProperty::New("d1y")); mitk::ReferenceCountWatcher::Pointer watcherD1y = new mitk::ReferenceCountWatcher(d1y); int refCountbeforeDS = watcherD1y->GetReferenceCount(); ds->Add(d1y, extra); mitk::DataNode::Pointer d2y = mitk::DataNode::New(); d2y->SetProperty("name", mitk::StringProperty::New("d2y")); ds->Add(d2y, extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1y") == d1y) && (ds->GetNamedNode("d2y") == d2y) && (ds->GetSources(d1y)->Size() == 1) // extra should be source of d1y && (ds->GetSources(d2y)->Size() == 1) // extra should be source of d2y && (ds->GetDerivations(extra)->Size() == 2) // d1y and d2y should be derived from extra , "add extra node"); ds->Remove(ds->GetDerivations(extra)); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1y") == nullptr) // d1y should be nullptr now && (ds->GetNamedNode("d2y") == nullptr) // d2y should be nullptr now && (refCountbeforeDS == watcherD1y->GetReferenceCount()), "Checking removal of subset of two derived nodes from one parent node"); ds->Remove(extra); MITK_TEST_CONDITION((ds->GetNamedNode("extra") == nullptr), "Checking removal of a parent node"); extra = nullptr; } /* Checking GetGrouptags() */ { const std::set groupTags = ds->GetGroupTags(); MITK_TEST_CONDITION((groupTags.size() == 2) && (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 1") != groupTags.end()) && (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 2") != groupTags.end()), "Checking GetGrouptags()"); } /* Checking Event handling */ DSEventReceiver listener; try { ds->AddNodeEvent += mitk::MessageDelegate1(&listener, &DSEventReceiver::OnAdd); ds->RemoveNodeEvent += mitk::MessageDelegate1(&listener, &DSEventReceiver::OnRemove); mitk::DataNode::Pointer extra = mitk::DataNode::New(); mitk::ReferenceCountWatcher::Pointer watcher = new mitk::ReferenceCountWatcher(extra); ds->Add(extra); MITK_TEST_CONDITION(listener.m_NodeAdded == extra.GetPointer(), "Checking AddEvent"); ds->Remove(extra); MITK_TEST_CONDITION(listener.m_NodeRemoved == extra.GetPointer(), "Checking RemoveEvent"); /* RemoveListener */ ds->AddNodeEvent -= mitk::MessageDelegate1(&listener, &DSEventReceiver::OnAdd); ds->RemoveNodeEvent -= mitk::MessageDelegate1(&listener, &DSEventReceiver::OnRemove); listener.m_NodeAdded = nullptr; listener.m_NodeRemoved = nullptr; ds->Add(extra); ds->Remove(extra); MITK_TEST_CONDITION((listener.m_NodeRemoved == nullptr) && (listener.m_NodeAdded == nullptr), "Checking RemoveListener"); std::cout << "Pointer handling after event handling: " << std::flush; extra = nullptr; // delete reference to the node. its memory should be freed now MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Pointer handling after event handling"); } catch (...) { /* cleanup */ ds->AddNodeEvent -= mitk::MessageDelegate1(&listener, &DSEventReceiver::OnAdd); ds->RemoveNodeEvent -= mitk::MessageDelegate1(&listener, &DSEventReceiver::OnRemove); MITK_TEST_FAILED_MSG(<< "Exception during object removal methods"); } // Checking ComputeBoundingGeometry3D method*/ const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetAll(); auto geometry = ds->ComputeBoundingGeometry3D(); MITK_TEST_CONDITION(geometry->CountTimeSteps() == 4, "Test for number or time steps with ComputeBoundingGeometry()"); mitk::TimeBounds timebounds = geometry->GetTimeBounds(); MITK_TEST_CONDITION((timebounds[0] == 0) && (timebounds[1] == 4), "Test for timebounds with ComputeBoundingGeometry()"); for (unsigned int i = 0; i < geometry->CountTimeSteps(); i++) { mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i); mitk::TimeBounds bounds = geometry->GetTimeBounds(i); MITK_TEST_CONDITION((bounds[0] == i) && (bounds[1] == i + 1), "Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()"); } geometry = ds->ComputeBoundingGeometry3D(all); MITK_TEST_CONDITION(geometry->CountTimeSteps() == 4, "Test for number or time steps with ComputeBoundingGeometry(allNodes)"); timebounds = geometry->GetTimeBounds(); MITK_TEST_CONDITION((timebounds[0] == 0) && (timebounds[1] == 4), "Test for timebounds with ComputeBoundingGeometry(allNodes)"); for (unsigned int i = 0; i < geometry->CountTimeSteps(); i++) { mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i); mitk::TimeBounds bounds = geometry->GetTimeBounds(i); MITK_TEST_CONDITION((bounds[0] == i) && (bounds[1] == i + 1), "Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()"); } // test for thread safety of DataStorage try { mitk::StandaloneDataStorage::Pointer standaloneDataStorage = mitk::StandaloneDataStorage::New(); ItkDeleteEventListener listener(standaloneDataStorage); { mitk::DataNode::Pointer emptyNode = mitk::DataNode::New(); mitk::DataNode *pEmptyNode = emptyNode; listener.SetNode(emptyNode); standaloneDataStorage->Add(emptyNode); emptyNode = nullptr; // emptyNode is still alive because standaloneDataStorage // owns it standaloneDataStorage->Remove(pEmptyNode); // this should not freeze the whole thing } } catch (...) { MITK_TEST_FAILED_MSG(<< "Exception during testing DataStorage thread safe"); } /* Clear DataStorage */ ds->Remove(ds->GetAll()); MITK_TEST_CONDITION(ds->GetAll()->Size() == 0, "Checking Clear DataStorage"); } diff --git a/Modules/Core/test/mitkExceptionTest.cpp b/Modules/Core/test/mitkExceptionTest.cpp index bd8c597b82..3b21794216 100644 --- a/Modules/Core/test/mitkExceptionTest.cpp +++ b/Modules/Core/test/mitkExceptionTest.cpp @@ -1,318 +1,318 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkExceptionMacro.h" #include "mitkTestingMacros.h" #include #include #include class SpecializedTestException : public mitk::Exception { public: mitkExceptionClassMacro(SpecializedTestException, mitk::Exception); }; class ExceptionTestClass : public itk::Object { public: mitkClassMacroItkParent(ExceptionTestClass, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) void throwExceptionManually() // this method is ONLY to test the constructor and no code example // normally exceptions should only be thrown by using the exception macro! { throw mitk::Exception("test.cpp", 155, "", ""); } void throwSpecializedExceptionManually() // this method is ONLY to test the constructor and no code example // normally exceptions should only be thrown by using the exception macro! { throw SpecializedTestException("test.cpp", 155, "", ""); } void throwExceptionManually(std::string message1, std::string message2) // this method is ONLY to test methods of mitk::Exception and no code example // normally exceptions should only be thrown by using the exception macro! { throw mitk::Exception("testfile.cpp", 155, message1.c_str(), "") << message2; } void throwExceptionWithThrowMacro() { mitkThrow() << "TEST EXCEPION THROWING WITH mitkThrow()"; } void throwExceptionWithThrowMacro(std::string message) { mitkThrow() << message.c_str(); } void throwSpecializedExceptionWithThrowMacro(std::string message) { mitkThrowException(mitk::Exception) << message; } void throwSpecializedExceptionWithThrowMacro2(std::string message) { mitkThrowException(SpecializedTestException) << message; } void reThrowExceptionWithReThrowMacro(std::string messageThrow, std::string messageReThrow) { try { throwExceptionWithThrowMacro(messageThrow); } catch (mitk::Exception &e) { mitkReThrow(e) << messageReThrow; } } static void TestExceptionConstructor() { bool exceptionThrown = false; ExceptionTestClass::Pointer myExceptionTestObject = ExceptionTestClass::New(); try { myExceptionTestObject->throwExceptionManually(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { exceptionThrown = true; } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing constructor of mitkException"); exceptionThrown = false; try { myExceptionTestObject->throwSpecializedExceptionManually(); } - catch (SpecializedTestException) + catch (const SpecializedTestException &) { exceptionThrown = true; } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing constructor specialized exception (deriving from mitkException)"); } static void TestExceptionMessageStream() { //##### this method is ONLY to test the streaming operators of the exceptions and //##### NO code example. Please do not instantiate exceptions by yourself in normal code! //##### Normally exceptions should only be thrown by using the exception macro! mitk::Exception myException = mitk::Exception("testfile.cpp", 111, "testmessage"); myException << " and additional stream"; MITK_TEST_CONDITION_REQUIRED(myException.GetDescription() == std::string("testmessage and additional stream"), "Testing mitkException message stream (adding std::string)"); myException.SetDescription("testmessage2"); myException << ' ' << 'a' << 'n' << 'd' << ' ' << 'c' << 'h' << 'a' << 'r' << 's'; MITK_TEST_CONDITION_REQUIRED(myException.GetDescription() == std::string("testmessage2 and chars"), "Testing mitkException message stream (adding single chars)"); myException.SetDescription("testmessage3"); myException << myException; // adding the object itself makes no sense but should work MITK_TEST_CONDITION_REQUIRED(myException.GetDescription() != std::string(""), "Testing mitkException message stream (adding object)"); SpecializedTestException mySpecializedException = SpecializedTestException("testfile.cpp", 111, "testmessage", "test"); mySpecializedException << " and additional stream"; MITK_TEST_CONDITION_REQUIRED( mySpecializedException.GetDescription() == std::string("testmessage and additional stream"), "Testing specialized exception message stream (adding std::string)"); } static void TestExceptionMessageStreamThrowing() { bool exceptionThrown = false; ExceptionTestClass::Pointer myExceptionTestObject = ExceptionTestClass::New(); std::string thrownMessage = ""; try { myExceptionTestObject->throwExceptionManually("message1", " and message2"); } - catch (mitk::Exception &e) + catch (const mitk::Exception &e) { thrownMessage = e.GetDescription(); exceptionThrown = true; } MITK_TEST_CONDITION_REQUIRED(exceptionThrown && (thrownMessage == std::string("message1 and message2")), "Testing throwing and streaming of mitk::Exception together.") } static void TestMitkThrowMacro() { bool exceptionThrown = false; ExceptionTestClass::Pointer myExceptionTestObject = ExceptionTestClass::New(); // case 1: test throwing try { myExceptionTestObject->throwExceptionWithThrowMacro(); } - catch (mitk::Exception) + catch (const mitk::Exception &) { exceptionThrown = true; } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing mitkThrow()"); // case 2: test message text exceptionThrown = false; std::string messageText = ""; try { myExceptionTestObject->throwExceptionWithThrowMacro("test123"); } - catch (mitk::Exception &e) + catch (const mitk::Exception &e) { exceptionThrown = true; messageText = e.GetDescription(); } MITK_TEST_CONDITION_REQUIRED((exceptionThrown && (messageText == "test123")), "Testing message test of mitkThrow()"); // case 3: specialized exception / command mitkThrow(mitk::Exception) exceptionThrown = false; messageText = ""; try { myExceptionTestObject->throwSpecializedExceptionWithThrowMacro("test123"); } - catch (mitk::Exception &e) + catch (const mitk::Exception &e) { exceptionThrown = true; messageText = e.GetDescription(); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown && messageText == "test123", "Testing special exception with mitkThrow(mitk::Exception)"); // case 4: specialized exception / command mitkThrow(mitk::SpecializedException) exceptionThrown = false; messageText = ""; try { myExceptionTestObject->throwSpecializedExceptionWithThrowMacro2("test123"); } - catch (SpecializedTestException &e) + catch (const SpecializedTestException &e) { exceptionThrown = true; messageText = e.GetDescription(); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown && messageText == "test123", "Testing special exception with mitkThrow(mitk::SpecializedException)"); } static void TestRethrowInformation() // this method is ONLY to test methods of mitk::Exception and no code example // normally exceptions should only be instantiated and thrown by using the exception macros! { // first: testing rethrow information methods, when no information is stored // case 1.1: method GetNumberOfRethrows() mitk::Exception e = mitk::Exception("test.cpp", 155, "", ""); MITK_TEST_CONDITION_REQUIRED(e.GetNumberOfRethrows() == 0, "Testing GetNumberOfRethrows() with empty rethrow information"); // case 1.2: GetRethrowData() with negative number { std::string file = "invalid"; int line = -1; std::string message = "invalid"; e.GetRethrowData(-1, file, line, message); MITK_TEST_CONDITION_REQUIRED(((file == "") && (line == 0) && (message == "")), "Testing GetRethrowData() with invalid rethrow number (negative)."); } // case 1.3: GetRethrowData() with number 0 { std::string file = "invalid"; int line = -1; std::string message = "invalid"; e.GetRethrowData(0, file, line, message); MITK_TEST_CONDITION_REQUIRED(((file == "") && (line == 0) && (message == "")), "Testing GetRethrowData() with non-existing rethrow number (0)."); } // case 1.4: GetRethrowData() with number 1 { std::string file = "invalid"; int line = -1; std::string message = "invalid"; e.GetRethrowData(1, file, line, message); MITK_TEST_CONDITION_REQUIRED(((file == "") && (line == 0) && (message == "")), "Testing GetRethrowData() with non-existing rethrow number (1)."); } // second: add rethrow data e.AddRethrowData("test2.cpp", 10, "Rethrow one"); MITK_TEST_CONDITION_REQUIRED(e.GetNumberOfRethrows() == 1, "Testing adding of rethrow data."); e.AddRethrowData("test3.cpp", 15, "Rethrow two"); MITK_TEST_CONDITION_REQUIRED(e.GetNumberOfRethrows() == 2, "Testing adding of more rethrow data."); // third: test if this rethrow data was stored properly { std::string file = "invalid"; int line = -1; std::string message = "invalid"; e.GetRethrowData(0, file, line, message); MITK_TEST_CONDITION_REQUIRED(((file == "test2.cpp") && (line == 10) && (message == "Rethrow one")), "Testing stored information of first rethrow."); } { std::string file = "invalid"; int line = -1; std::string message = "invalid"; e.GetRethrowData(1, file, line, message); MITK_TEST_CONDITION_REQUIRED(((file == "test3.cpp") && (line == 15) && (message == "Rethrow two")), "Testing stored information of second rethrow."); } } static void TestRethrowMacro() { bool exceptionThrown = false; std::string message = ""; ExceptionTestClass::Pointer myExceptionTestObject = ExceptionTestClass::New(); // case 1: test throwing try { myExceptionTestObject->reThrowExceptionWithReThrowMacro("Test original message.", "Test rethrow message."); } - catch (mitk::Exception &e) + catch (const mitk::Exception &e) { message = e.GetDescription(); exceptionThrown = true; } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing mitkReThrow()"); MITK_TEST_CONDITION_REQUIRED(message == "Test original message.Test rethrow message.", "Testing message/descriprion after rethrow.") } }; int mitkExceptionTest(int /*argc*/, char * /*argv*/ []) { MITK_TEST_BEGIN("MITKException"); ExceptionTestClass::TestExceptionConstructor(); ExceptionTestClass::TestExceptionMessageStream(); ExceptionTestClass::TestExceptionMessageStreamThrowing(); ExceptionTestClass::TestMitkThrowMacro(); ExceptionTestClass::TestRethrowInformation(); ExceptionTestClass::TestRethrowMacro(); MITK_TEST_END(); } diff --git a/Modules/Core/test/mitkImageSliceSelectorTest.cpp b/Modules/Core/test/mitkImageSliceSelectorTest.cpp index 37f9954b43..f0099ec45b 100644 --- a/Modules/Core/test/mitkImageSliceSelectorTest.cpp +++ b/Modules/Core/test/mitkImageSliceSelectorTest.cpp @@ -1,211 +1,211 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include int mitkImageSliceSelectorTest(int argc, char *argv[]) { int slice_nr = 1; std::cout << "Loading file: "; if (argc == 0) { std::cout << "no file specified [FAILED]" << std::endl; return EXIT_FAILURE; } mitk::Image::Pointer image; try { image = mitk::IOUtil::Load(argv[1]); } catch (const mitk::Exception &) { std::cout << "file not an image - test will not be applied [PASSED]" << std::endl; std::cout << "[TEST DONE]" << std::endl; return EXIT_SUCCESS; } catch (itk::ExceptionObject &ex) { std::cout << "Exception: " << ex << "[FAILED]" << std::endl; return EXIT_FAILURE; } if (image->GetDimension(2) < 2) slice_nr = 0; // Take a slice mitk::ImageSliceSelector::Pointer slice = mitk::ImageSliceSelector::New(); slice->SetInput(image); slice->SetSliceNr(slice_nr); slice->Update(); std::cout << "Testing IsInitialized(): "; if (slice->GetOutput()->IsInitialized() == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing IsSliceSet(): "; if (slice->GetOutput()->IsSliceSet(0) == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; /* deactivated because IpPic is not available any more (see bug 16662) if(itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameExtension(argv[1])).find(".pic")!=std::string::npos) { std::cout << "Testing whether the slice is identical with a slice loaded by mitkIpPicGetSlice:"; mitkIpPicDescriptor *picslice = mitkIpPicGetSlice(argv[1], nullptr, (image->GetDimension(2)-1-slice_nr)+1); int i, size = _mitkIpPicSize(picslice); char * p1 = (char*)slice->GetPic()->data; char * p2 = (char*)picslice->data; //picslice->info->write_protect=mitkIpFalse; //mitkIpPicPut("C:\\1aaaaIPPIC.pic", picslice); //mitkIpPicPut("C:\\1aaaaSEL.pic", slice->GetPic()); for(i=0; iSetInput(image); //the output size of this filter is smaller than the of the input!! cyl2cart->SetTargetXSize( 64 ); //Use the same slice-selector again, this time to take a slice of the filtered image //which is smaller than the one of the old input!! slice->SetInput(cyl2cart->GetOutput()); slice->SetSliceNr(1); //The requested region is still the old one, //therefore the following results in most ITK versions //in an exception! slice->Update(); //If no exception occured, check that the requested region is now //the one of the smaller image if(cyl2cart->GetOutput()->GetLargestPossibleRegion().GetSize()[0]!=64) { std::cout<<"Part 1 [FAILED]"<GetOutput()->GetDimensions()[0]!=64) || (cyl2cart->GetOutput()->GetDimensions()[1]!=64)) { std::cout<<"Part 1b [FAILED]"<ResetPipeline(); } */ try { slice->UpdateLargestPossibleRegion(); } - catch (itk::ExceptionObject) + catch (const itk::ExceptionObject &) { std::cout << "Part 2 [FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "Part 2 [PASSED]" << std::endl; std::cout << "Testing IsInitialized(): "; if (slice->GetOutput()->IsInitialized() == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing IsSliceSet(): "; if (slice->GetOutput()->IsSliceSet(0) == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; if (image->GetDimension(3) > 1) { int time = image->GetDimension(3) - 1; std::cout << "Testing 3D+t: Setting time to " << time << ": "; slice->SetTimeNr(time); if (slice->GetTimeNr() != time) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing 3D+t: Updating slice: "; slice->Update(); if (slice->GetOutput()->IsInitialized() == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing 3D+t: IsSliceSet(): "; if (slice->GetOutput()->IsSliceSet(0) == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing 3D+t: First slice in reader available: "; if (image->IsSliceSet(0, time) == false) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; } std::cout << "[TEST DONE]" << std::endl; return EXIT_SUCCESS; } diff --git a/Modules/CppMicroServices/core/src/util/usThreads_p.h b/Modules/CppMicroServices/core/src/util/usThreads_p.h index 8de2cc3beb..7f87fc4fbe 100644 --- a/Modules/CppMicroServices/core/src/util/usThreads_p.h +++ b/Modules/CppMicroServices/core/src/util/usThreads_p.h @@ -1,329 +1,329 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USTHREADINGMODEL_H #define USTHREADINGMODEL_H #include #ifdef US_ENABLE_THREADING_SUPPORT // Atomic compiler intrinsics #if defined(US_PLATFORM_APPLE) // OSAtomic.h optimizations only used in 10.5 and later, deprecated in 10.12 #include #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 && MAC_OS_X_VERSION_MAX_ALLOWED < 101200 #include #define US_ATOMIC_OPTIMIZATION_APPLE #endif #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) # include #else # include #endif #define US_ATOMIC_OPTIMIZATION_GNUC #endif // Mutex support #ifdef US_PLATFORM_WINDOWS #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #ifndef NOMINMAX #define NOMINMAX #endif #include #define US_THREADS_MUTEX(x) HANDLE (x); #define US_THREADS_MUTEX_INIT(x) #define US_THREADS_MUTEX_CTOR(x) : x(::CreateMutex(nullptr, FALSE, nullptr)) #define US_THREADS_MUTEX_DELETE(x) ::CloseHandle (x) #define US_THREADS_MUTEX_LOCK(x) ::WaitForSingleObject (x, INFINITE) #define US_THREADS_MUTEX_UNLOCK(x) ::ReleaseMutex (x) #define US_THREADS_LONG LONG #define US_ATOMIC_OPTIMIZATION #define US_ATOMIC_INCREMENT(x) IntType n = InterlockedIncrement(x) #define US_ATOMIC_DECREMENT(x) IntType n = InterlockedDecrement(x) #define US_ATOMIC_ASSIGN(l, r) InterlockedExchange(l, r) #elif defined(US_PLATFORM_POSIX) #include - #define US_THREADS_MUTEX(x) pthread_mutex_t (x); + #define US_THREADS_MUTEX(x) pthread_mutex_t x; #define US_THREADS_MUTEX_INIT(x) ::pthread_mutex_init(&x, 0) #define US_THREADS_MUTEX_CTOR(x) : x() #define US_THREADS_MUTEX_DELETE(x) ::pthread_mutex_destroy (&x) #define US_THREADS_MUTEX_LOCK(x) ::pthread_mutex_lock (&x) #define US_THREADS_MUTEX_UNLOCK(x) ::pthread_mutex_unlock (&x) #define US_ATOMIC_OPTIMIZATION #if defined(US_ATOMIC_OPTIMIZATION_APPLE) #if defined (__LP64__) && __LP64__ #define US_THREADS_LONG volatile int64_t #define US_ATOMIC_INCREMENT(x) IntType n = OSAtomicIncrement64Barrier(x) #define US_ATOMIC_DECREMENT(x) IntType n = OSAtomicDecrement64Barrier(x) #define US_ATOMIC_ASSIGN(l, v) OSAtomicCompareAndSwap64Barrier(*l, v, l) #else #define US_THREADS_LONG volatile int32_t #define US_ATOMIC_INCREMENT(x) IntType n = OSAtomicIncrement32Barrier(x) #define US_ATOMIC_DECREMENT(x) IntType n = OSAtomicDecrement32Barrier(x) #define US_ATOMIC_ASSIGN(l, v) OSAtomicCompareAndSwap32Barrier(*l, v, l) #endif #elif defined(US_ATOMIC_OPTIMIZATION_GNUC) #define US_THREADS_LONG _Atomic_word #define US_ATOMIC_INCREMENT(x) IntType n = __sync_add_and_fetch(x, 1) #define US_ATOMIC_DECREMENT(x) IntType n = __sync_add_and_fetch(x, -1) #define US_ATOMIC_ASSIGN(l, v) __sync_val_compare_and_swap(l, *l, v) #else #define US_THREADS_LONG long #undef US_ATOMIC_OPTIMIZATION #define US_ATOMIC_INCREMENT(x) m_AtomicMtx.Lock(); \ IntType n = ++(*x); \ m_AtomicMtx.Unlock() #define US_ATOMIC_DECREMENT(x) m_AtomicMtx.Lock(); \ IntType n = --(*x); \ m_AtomicMtx.Unlock() #define US_ATOMIC_ASSIGN(l, v) m_AtomicMtx.Lock(); \ *l = v; \ m_AtomicMtx.Unlock() #endif #endif #else // single threaded #define US_THREADS_MUTEX(x) #define US_THREADS_MUTEX_INIT(x) #define US_THREADS_MUTEX_CTOR(x) #define US_THREADS_MUTEX_DELETE(x) #define US_THREADS_MUTEX_LOCK(x) #define US_THREADS_MUTEX_UNLOCK(x) #define US_THREADS_LONG int #define US_ATOMIC_INCREMENT(x) IntType n = ++(*x); #define US_ATOMIC_DECREMENT(x) IntType n = --(*x); #define US_ATOMIC_ASSIGN(l, r) *l = r; #endif US_BEGIN_NAMESPACE class Mutex { public: Mutex() US_THREADS_MUTEX_CTOR(m_Mtx) { US_THREADS_MUTEX_INIT(m_Mtx); } ~Mutex() { US_THREADS_MUTEX_DELETE(m_Mtx); } void Lock() { US_THREADS_MUTEX_LOCK(m_Mtx); } void Unlock() { US_THREADS_MUTEX_UNLOCK(m_Mtx); } private: template friend class WaitCondition; // Copy-constructor not implemented. Mutex(const Mutex &); // Copy-assignement operator not implemented. Mutex & operator = (const Mutex &); US_THREADS_MUTEX(m_Mtx) }; class MutexLock { public: typedef Mutex MutexType; MutexLock(MutexType& mtx) : m_Mtx(&mtx) { m_Mtx->Lock(); } ~MutexLock() { m_Mtx->Unlock(); } private: MutexType* m_Mtx; // purposely not implemented MutexLock(const MutexLock&); MutexLock& operator=(const MutexLock&); }; class AtomicCounter { public: typedef US_THREADS_LONG IntType; AtomicCounter(int value = 0) : m_Counter(value) {} IntType AtomicIncrement() const { US_ATOMIC_INCREMENT(&m_Counter); return n; } IntType AtomicIncrement(volatile IntType& lval) const { US_ATOMIC_INCREMENT(&lval); return n; } IntType AtomicDecrement() const { US_ATOMIC_DECREMENT(&m_Counter); return n; } IntType AtomicDecrement(volatile IntType& lval) const { US_ATOMIC_DECREMENT(&lval); return n; } void AtomicAssign(volatile IntType& lval) const { US_ATOMIC_ASSIGN(&lval, m_Counter); } void AtomicAssign(volatile IntType& lval, const IntType val) const { US_ATOMIC_ASSIGN(&lval, val); } mutable IntType m_Counter; private: #if !defined(US_ATOMIC_OPTIMIZATION) mutable Mutex m_AtomicMtx; #endif }; class MutexLockingStrategy { public: MutexLockingStrategy() #ifdef US_ENABLE_THREADING_SUPPORT : m_Mtx() #endif {} MutexLockingStrategy(const MutexLockingStrategy&) #ifdef US_ENABLE_THREADING_SUPPORT : m_Mtx() #endif {} class Lock; friend class Lock; class Lock { public: #ifdef US_ENABLE_THREADING_SUPPORT // Lock object explicit Lock(const MutexLockingStrategy& host) : m_Host(host) { m_Host.m_Mtx.Lock(); } // Lock object explicit Lock(const MutexLockingStrategy* host) : m_Host(*host) { m_Host.m_Mtx.Lock(); } // Unlock object ~Lock() { m_Host.m_Mtx.Unlock(); } #else explicit Lock(const MutexLockingStrategy&) {} explicit Lock(const MutexLockingStrategy*) {} #endif private: // private by design Lock(); Lock(const Lock&); Lock& operator=(const Lock&); #ifdef US_ENABLE_THREADING_SUPPORT const MutexLockingStrategy& m_Host; #endif }; protected: #ifdef US_ENABLE_THREADING_SUPPORT mutable Mutex m_Mtx; #endif }; class NoLockingStrategy { }; US_END_NAMESPACE #include US_BEGIN_NAMESPACE template class WaitConditionStrategy = NoWaitCondition > class MultiThreaded : public LockingStrategy, public WaitConditionStrategy > { friend class WaitConditionStrategy >; }; US_END_NAMESPACE #endif // USTHREADINGMODEL_H diff --git a/Modules/CppMicroServices/core/test/usModuleTest.cpp b/Modules/CppMicroServices/core/test/usModuleTest.cpp index 583cd175d6..1eab5159c3 100644 --- a/Modules/CppMicroServices/core/test/usModuleTest.cpp +++ b/Modules/CppMicroServices/core/test/usModuleTest.cpp @@ -1,350 +1,350 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include #include #include #include #include #include "usTestUtilModuleListener.h" #include "usTestDriverActivator.h" #include "usTestingMacros.h" #include "usTestingConfig.h" US_USE_NAMESPACE namespace { #ifdef US_PLATFORM_WINDOWS static const std::string LIB_PATH = US_RUNTIME_OUTPUT_DIRECTORY; static const char PATH_SEPARATOR = '\\'; #else static const std::string LIB_PATH = US_LIBRARY_OUTPUT_DIRECTORY; static const char PATH_SEPARATOR = '/'; #endif // Check that the executable's activator was loaded and called void frame01() { US_TEST_CONDITION_REQUIRED(TestDriverActivator::LoadCalled(), "ModuleActivator::Load() called for executable") } // Verify that the same member function pointers registered as listeners // with different receivers works. void frame02a() { ModuleContext* mc = GetModuleContext(); TestModuleListener listener1; TestModuleListener listener2; try { mc->RemoveModuleListener(&listener1, &TestModuleListener::ModuleChanged); mc->AddModuleListener(&listener1, &TestModuleListener::ModuleChanged); mc->RemoveModuleListener(&listener2, &TestModuleListener::ModuleChanged); mc->AddModuleListener(&listener2, &TestModuleListener::ModuleChanged); } catch (const std::logic_error& ise) { US_TEST_FAILED_MSG( << "module listener registration failed " << ise.what() << " : frameSL02a:FAIL" ); } SharedLibrary target(LIB_PATH, "TestModuleA"); #ifdef US_BUILD_SHARED_LIBS // Start the test target try { target.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what() << " + in frameSL02a:FAIL" ); } #endif Module* moduleA = ModuleRegistry::GetModule("TestModuleA"); US_TEST_CONDITION_REQUIRED(moduleA != nullptr, "Test for existing module TestModuleA") std::vector pEvts; #ifdef US_BUILD_SHARED_LIBS pEvts.push_back(ModuleEvent(ModuleEvent::LOADING, moduleA)); pEvts.push_back(ModuleEvent(ModuleEvent::LOADED, moduleA)); #endif std::vector seEvts; US_TEST_CONDITION(listener1.CheckListenerEvents(pEvts, seEvts), "Check first module listener") US_TEST_CONDITION(listener2.CheckListenerEvents(pEvts, seEvts), "Check second module listener") mc->RemoveModuleListener(&listener1, &TestModuleListener::ModuleChanged); mc->RemoveModuleListener(&listener2, &TestModuleListener::ModuleChanged); target.Unload(); } // Verify information from the ModuleInfo struct void frame005a(ModuleContext* mc) { Module* m = mc->GetModule(); // check expected headers US_TEST_CONDITION("main" == m->GetName(), "Test module name") US_TEST_CONDITION(ModuleVersion(0,1,0) == m->GetVersion(), "Test test driver module version") US_TEST_CONDITION(ModuleVersion(CppMicroServices_MAJOR_VERSION, CppMicroServices_MINOR_VERSION, CppMicroServices_PATCH_VERSION) == ModuleRegistry::GetModule(1)->GetVersion(), "Test CppMicroServices version") } // Get context id, location and status of the module void frame010a(ModuleContext* mc) { Module* m = mc->GetModule(); long int contextid = m->GetModuleId(); US_DEBUG << "CONTEXT ID:" << contextid; std::string location = m->GetLocation(); US_DEBUG << "LOCATION:" << location; US_TEST_CONDITION(!location.empty(), "Test for non-empty module location") US_TEST_CONDITION(m->IsLoaded(), "Test for loaded flag") US_TEST_CONDITION(ModuleSettings::GetStoragePath().empty(), "Test for empty base storage path") US_TEST_CONDITION(m->GetModuleContext()->GetDataFile("").empty(), "Test for empty data path") US_TEST_CONDITION(m->GetModuleContext()->GetDataFile("bla").empty(), "Test for empty data file path") } //---------------------------------------------------------------------------- //Test result of GetService(ServiceReference()). Should throw std::invalid_argument void frame018a(ModuleContext* mc) { try { mc->GetService(ServiceReferenceU()); US_DEBUG << "Got service object, expected std::invalid_argument exception"; US_TEST_FAILED_MSG(<< "Got service object, excpected std::invalid_argument exception") } catch (const std::invalid_argument& ) {} catch (...) { US_TEST_FAILED_MSG(<< "Got wrong exception, expected std::invalid_argument") } } // Load libA and check that it exists and that the service it registers exists, // also check that the expected events occur and that the storage paths are correct void frame020a(ModuleContext* mc, TestModuleListener& listener, #ifdef US_BUILD_SHARED_LIBS SharedLibrary& libA) { try { libA.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "Load module exception: " << e.what()) } #else SharedLibrary& /*libA*/) { #endif ModuleSettings::SetStoragePath(std::string("/tmp") + PATH_SEPARATOR); US_TEST_CONDITION(ModuleSettings::GetStoragePath() == "/tmp", "Test for valid base storage path") Module* moduleA = ModuleRegistry::GetModule("TestModuleA"); US_TEST_CONDITION_REQUIRED(moduleA != nullptr, "Test for existing module TestModuleA") US_TEST_CONDITION(moduleA->GetName() == "TestModuleA", "Test module name") std::cout << moduleA->GetModuleContext()->GetDataFile("") << std::endl; std::stringstream ss; ss << moduleA->GetModuleId(); const std::string baseStoragePath = std::string("/tmp") + PATH_SEPARATOR + ss.str() + "_TestModuleA" + PATH_SEPARATOR; US_TEST_CONDITION(moduleA->GetModuleContext()->GetDataFile("") == baseStoragePath, "Test for valid data path") US_TEST_CONDITION(moduleA->GetModuleContext()->GetDataFile("bla") == baseStoragePath + "bla", "Test for valid data file path") // Check if libA registered the expected service try { ServiceReferenceU sr1 = mc->GetServiceReference("us::TestModuleAService"); InterfaceMap o1 = mc->GetService(sr1); US_TEST_CONDITION(!o1.empty(), "Test if service object found"); try { US_TEST_CONDITION(mc->UngetService(sr1), "Test if Service UnGet returns true"); } - catch (const std::logic_error le) + catch (const std::logic_error& le) { US_TEST_FAILED_MSG(<< "UnGetService exception: " << le.what()) } // check the listeners for events std::vector pEvts; #ifdef US_BUILD_SHARED_LIBS pEvts.push_back(ModuleEvent(ModuleEvent::LOADING, moduleA)); pEvts.push_back(ModuleEvent(ModuleEvent::LOADED, moduleA)); #endif std::vector seEvts; #ifdef US_BUILD_SHARED_LIBS seEvts.push_back(ServiceEvent(ServiceEvent::REGISTERED, sr1)); #endif US_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } catch (const ServiceException& /*se*/) { US_TEST_FAILED_MSG(<< "test module, expected service not found"); } US_TEST_CONDITION(moduleA->IsLoaded() == true, "Test if loaded correctly"); } // Unload libA and check for correct events void frame030b(ModuleContext* mc, TestModuleListener& listener, SharedLibrary& libA) { Module* moduleA = ModuleRegistry::GetModule("TestModuleA"); US_TEST_CONDITION_REQUIRED(moduleA != nullptr, "Test for non-null module") ServiceReferenceU sr1 = mc->GetServiceReference("us::TestModuleAService"); US_TEST_CONDITION(sr1, "Test for valid service reference") try { libA.Unload(); #ifdef US_BUILD_SHARED_LIBS US_TEST_CONDITION(moduleA->IsLoaded() == false, "Test for unloaded state") #endif } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "UnLoad module exception: " << e.what()) } std::vector pEvts; #ifdef US_BUILD_SHARED_LIBS pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADING, moduleA)); pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADED, moduleA)); #endif std::vector seEvts; #ifdef US_BUILD_SHARED_LIBS seEvts.push_back(ServiceEvent(ServiceEvent::UNREGISTERING, sr1)); #endif US_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } struct LocalListener { void ServiceChanged(const ServiceEvent) {} }; // Add a service listener with a broken LDAP filter to Get an exception void frame045a(ModuleContext* mc) { LocalListener sListen1; std::string brokenFilter = "A broken LDAP filter"; try { mc->AddServiceListener(&sListen1, &LocalListener::ServiceChanged, brokenFilter); } catch (const std::invalid_argument& /*ia*/) { //assertEquals("InvalidSyntaxException.GetFilter should be same as input string", brokenFilter, ise.GetFilter()); } catch (...) { US_TEST_FAILED_MSG(<< "test module, wrong exception on broken LDAP filter:"); } } } // end unnamed namespace int usModuleTest(int /*argc*/, char* /*argv*/[]) { //US_TEST_BEGIN("ModuleTest"); std::vector modules = ModuleRegistry::GetModules(); for (std::vector::iterator iter = modules.begin(), iterEnd = modules.end(); iter != iterEnd; ++iter) { std::cout << "----- " << (*iter)->GetName() << std::endl; } frame01(); frame02a(); ModuleContext* mc = GetModuleContext(); TestModuleListener listener; try { mc->AddModuleListener(&listener, &TestModuleListener::ModuleChanged); } catch (const std::logic_error& ise) { US_TEST_OUTPUT( << "module listener registration failed " << ise.what() ); throw; } try { mc->AddServiceListener(&listener, &TestModuleListener::ServiceChanged); } catch (const std::logic_error& ise) { US_TEST_OUTPUT( << "service listener registration failed " << ise.what() ); throw; } frame005a(mc); frame010a(mc); frame018a(mc); SharedLibrary libA(LIB_PATH, "TestModuleA"); frame020a(mc, listener, libA); frame030b(mc, listener, libA); frame045a(mc); mc->RemoveModuleListener(&listener, &TestModuleListener::ModuleChanged); mc->RemoveServiceListener(&listener, &TestModuleListener::ServiceChanged); //US_TEST_END() return 0; } diff --git a/Modules/CppMicroServices/core/test/usStaticModuleTest.cpp b/Modules/CppMicroServices/core/test/usStaticModuleTest.cpp index 049606c4b9..8b6994f189 100644 --- a/Modules/CppMicroServices/core/test/usStaticModuleTest.cpp +++ b/Modules/CppMicroServices/core/test/usStaticModuleTest.cpp @@ -1,183 +1,183 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include #include #include #include #include "usTestUtilModuleListener.h" #include "usTestingMacros.h" #include "usTestingConfig.h" US_USE_NAMESPACE namespace { #ifdef US_PLATFORM_WINDOWS static const std::string LIB_PATH = US_RUNTIME_OUTPUT_DIRECTORY; #else static const std::string LIB_PATH = US_LIBRARY_OUTPUT_DIRECTORY; #endif // Load libTestModuleB and check that it exists and that the service it registers exists, // also check that the expected events occur void frame020a(ModuleContext* mc, TestModuleListener& listener, #ifdef US_BUILD_SHARED_LIBS SharedLibrary& libB) { try { libB.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "Load module exception: " << e.what()) } #else SharedLibrary& /*libB*/) { #endif Module* moduleB = ModuleRegistry::GetModule("TestModuleB"); US_TEST_CONDITION_REQUIRED(moduleB != nullptr, "Test for existing module TestModuleB") Module* moduleImportedByB = ModuleRegistry::GetModule("TestModuleImportedByB"); US_TEST_CONDITION_REQUIRED(moduleImportedByB != nullptr, "Test for existing module TestModuleImportedByB") US_TEST_CONDITION(moduleB->GetName() == "TestModuleB", "Test module name") // Check if libB registered the expected service try { std::vector refs = mc->GetServiceReferences("us::TestModuleBService"); US_TEST_CONDITION_REQUIRED(refs.size() == 2, "Test that both the service from the shared and imported library are regsitered"); InterfaceMap o1 = mc->GetService(refs.front()); US_TEST_CONDITION(!o1.empty(), "Test if first service object found"); InterfaceMap o2 = mc->GetService(refs.back()); US_TEST_CONDITION(!o2.empty(), "Test if second service object found"); try { US_TEST_CONDITION(mc->UngetService(refs.front()), "Test if Service UnGet for first service returns true"); US_TEST_CONDITION(mc->UngetService(refs.back()), "Test if Service UnGet for second service returns true"); } - catch (const std::logic_error le) + catch (const std::logic_error &le) { US_TEST_FAILED_MSG(<< "UnGetService exception: " << le.what()) } // check the listeners for events std::vector pEvts; #ifdef US_BUILD_SHARED_LIBS pEvts.push_back(ModuleEvent(ModuleEvent::LOADING, moduleB)); pEvts.push_back(ModuleEvent(ModuleEvent::LOADED, moduleB)); pEvts.push_back(ModuleEvent(ModuleEvent::LOADING, moduleImportedByB)); pEvts.push_back(ModuleEvent(ModuleEvent::LOADED, moduleImportedByB)); #endif std::vector seEvts; #ifdef US_BUILD_SHARED_LIBS seEvts.push_back(ServiceEvent(ServiceEvent::REGISTERED, refs.back())); seEvts.push_back(ServiceEvent(ServiceEvent::REGISTERED, refs.front())); #endif US_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } catch (const ServiceException& /*se*/) { US_TEST_FAILED_MSG(<< "test module, expected service not found"); } #ifdef US_BUILD_SHARED_LIBS US_TEST_CONDITION(moduleB->IsLoaded() == true, "Test if loaded correctly"); #endif } // Unload libB and check for correct events void frame030b(ModuleContext* mc, TestModuleListener& listener, SharedLibrary& libB) { Module* moduleB = ModuleRegistry::GetModule("TestModuleB"); US_TEST_CONDITION_REQUIRED(moduleB != nullptr, "Test for non-null module") Module* moduleImportedByB = ModuleRegistry::GetModule("TestModuleImportedByB"); US_TEST_CONDITION_REQUIRED(moduleImportedByB != nullptr, "Test for non-null module") std::vector refs = mc->GetServiceReferences("us::TestModuleBService"); US_TEST_CONDITION(refs.front(), "Test for first valid service reference") US_TEST_CONDITION(refs.back(), "Test for second valid service reference") try { libB.Unload(); #ifdef US_BUILD_SHARED_LIBS US_TEST_CONDITION(moduleB->IsLoaded() == false, "Test for unloaded state") #endif } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "UnLoad module exception: " << e.what()) } std::vector pEvts; #ifdef US_BUILD_SHARED_LIBS pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADING, moduleImportedByB)); pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADED, moduleImportedByB)); pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADING, moduleB)); pEvts.push_back(ModuleEvent(ModuleEvent::UNLOADED, moduleB)); #endif std::vector seEvts; #ifdef US_BUILD_SHARED_LIBS seEvts.push_back(ServiceEvent(ServiceEvent::UNREGISTERING, refs.front())); seEvts.push_back(ServiceEvent(ServiceEvent::UNREGISTERING, refs.back())); #endif US_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } } // end unnamed namespace int usStaticModuleTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("StaticModuleTest"); ModuleContext* mc = GetModuleContext(); TestModuleListener listener; ModuleListenerRegistrationHelper ml(mc, &listener, &TestModuleListener::ModuleChanged); ServiceListenerRegistrationHelper sl(mc, &listener, &TestModuleListener::ServiceChanged); SharedLibrary libB(LIB_PATH, "TestModuleB"); frame020a(mc, listener, libB); frame030b(mc, listener, libB); US_TEST_END() } diff --git a/Modules/CppMicroServices/core/test/usTestingMacros.h b/Modules/CppMicroServices/core/test/usTestingMacros.h index b7a2b2d04b..b8ce72e9a1 100644 --- a/Modules/CppMicroServices/core/test/usTestingMacros.h +++ b/Modules/CppMicroServices/core/test/usTestingMacros.h @@ -1,138 +1,138 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USTESTINGMACROS_H_ #define USTESTINGMACROS_H_ #include #include #include #include #include "usTestManager.h" US_BEGIN_NAMESPACE /** \brief Indicate a failed test. */ class TestFailedException : public std::exception { public: TestFailedException() {} }; US_END_NAMESPACE /** * * \brief Output some text without generating a terminating newline. * * */ #define US_TEST_OUTPUT_NO_ENDL(x) \ std::cout x << std::flush; /** \brief Output some text. */ #define US_TEST_OUTPUT(x) \ US_TEST_OUTPUT_NO_ENDL(x << "\n") /** \brief Do some general test preparations. Must be called first in the main test function. */ #define US_TEST_BEGIN(testName) \ std::string usTestName(#testName); \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().Initialize(); \ try { /** \brief Fail and finish test with message MSG */ #define US_TEST_FAILED_MSG(MSG) \ US_TEST_OUTPUT(MSG) \ throw US_PREPEND_NAMESPACE(TestFailedException)(); /** \brief Must be called last in the main test function. */ #define US_TEST_END() \ } catch (const US_PREPEND_NAMESPACE(TestFailedException)&) { \ US_TEST_OUTPUT(<< "Further test execution skipped.") \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestFailed(); \ } catch (const std::exception& ex) { \ US_TEST_OUTPUT(<< "Exception occured " << ex.what()) \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestFailed(); \ } \ if (US_PREPEND_NAMESPACE(TestManager)::GetInstance().NumberOfFailedTests() > 0) { \ US_TEST_OUTPUT(<< usTestName << ": [DONE FAILED] , subtests passed: " << \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().NumberOfPassedTests() << " failed: " << \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().NumberOfFailedTests() ) \ return EXIT_FAILURE; \ } else { \ US_TEST_OUTPUT(<< usTestName << ": " \ << US_PREPEND_NAMESPACE(TestManager)::GetInstance().NumberOfPassedTests() \ << " tests [DONE PASSED]") \ return EXIT_SUCCESS; \ } #define US_TEST_CONDITION(COND,MSG) \ US_TEST_OUTPUT_NO_ENDL(<< MSG) \ if ( ! (COND) ) { \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestFailed(); \ US_TEST_OUTPUT(<< " [FAILED]\n" << "In " << __FILE__ \ << ", line " << __LINE__ \ << ": " #COND " : [FAILED]") \ } else { \ US_TEST_OUTPUT(<< " [PASSED]") \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestPassed(); \ } #define US_TEST_CONDITION_REQUIRED(COND,MSG) \ US_TEST_OUTPUT_NO_ENDL(<< MSG) \ if ( ! (COND) ) { \ US_TEST_FAILED_MSG(<< " [FAILED]\n" << " +--> in " << __FILE__ \ << ", line " << __LINE__ \ << ", expression is false: \"" #COND "\"") \ } else { \ US_TEST_OUTPUT(<< " [PASSED]") \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestPassed(); \ } /** * \brief Begin block which should be checked for exceptions * * This macro, together with US_TEST_FOR_EXCEPTION_END, can be used * to test whether a code block throws an expected exception. The test FAILS if the * exception is NOT thrown. */ #define US_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ try { #define US_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestFailed(); \ US_TEST_OUTPUT( << "Expected an '" << #EXCEPTIONCLASS << "' exception. [FAILED]") \ } \ - catch (EXCEPTIONCLASS) { \ + catch (const EXCEPTIONCLASS &) { \ US_TEST_OUTPUT(<< "Caught an expected '" << #EXCEPTIONCLASS \ << "' exception. [PASSED]") \ US_PREPEND_NAMESPACE(TestManager)::GetInstance().TestPassed(); \ } /** * \brief Simplified version of US_TEST_FOR_EXCEPTION_BEGIN / END for * a single statement */ #define US_TEST_FOR_EXCEPTION(EXCEPTIONCLASS, STATEMENT) \ US_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ STATEMENT ; \ US_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) #endif // USTESTINGMACROS_H_ diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp index 65cc609884..81e0e49cdc 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp @@ -1,148 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkPAComposedVolume.h" #include "mitkIOUtil.h" #include "mitkImageReadAccessor.h" #include class mitkPhotoacousticComposedVolumeTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticComposedVolumeTestSuite); MITK_TEST(TestCreateAndDestructComposedVolume); MITK_TEST(TestAccessInvalidFluenceComponent); MITK_TEST(TestAccessInvalidFluenceComponentIndex); MITK_TEST(TestAddMultiplePairs); MITK_TEST(TestSortFunctionality); MITK_TEST(TestAccessInvalidFluenceComponentForYOffset); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::ComposedVolume::Pointer m_ComposedVolume; mitk::pa::TissueGeneratorParameters::Pointer m_DefaultParameters; mitk::pa::InSilicoTissueVolume::Pointer m_InSilicoTissueVolume; public: void setUp() override { m_DefaultParameters = mitk::pa::TissueGeneratorParameters::New(); m_DefaultParameters->SetXDim(5); m_DefaultParameters->SetYDim(5); m_DefaultParameters->SetZDim(5); m_InSilicoTissueVolume = mitk::pa::InSilicoTissueVolume::New(m_DefaultParameters); m_ComposedVolume = mitk::pa::ComposedVolume::New(m_InSilicoTissueVolume); } mitk::pa::FluenceYOffsetPair::Pointer createFluenceYOffsetPair(double value, double yOffset) { auto* data = new double[125]; for (int i = 0; i < 125; ++i) data[i] = value; mitk::pa::Volume::Pointer volume = mitk::pa::Volume::New(data, 5, 5, 5); return mitk::pa::FluenceYOffsetPair::New(volume, yOffset); } void TestCreateAndDestructComposedVolume() { CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 0); } void TestAccessInvalidFluenceComponent() { bool caughtException = false; try { m_ComposedVolume->GetFluenceValue(0, 0, 0, 0); } - catch (mitk::Exception e) + catch (const mitk::Exception &e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); } void TestAddMultiplePairs() { m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 1); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(1, 1)); CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 2); } void TestSortFunctionality() { m_ComposedVolume->AddSlice(createFluenceYOffsetPair(2, 2)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(-1, -1)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(1, 1)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(-2, -2)); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(0, 0, 2, 0) == 2); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(1, 0, 2, 0) == -1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(2, 0, 2, 0) == 1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(3, 0, 2, 0) == 0); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(4, 0, 2, 0) == -2); m_ComposedVolume->Sort(); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(0, 0, 2, 0) == -2); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(1, 0, 2, 0) == -1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(2, 0, 2, 0) == 0); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(3, 0, 2, 0) == 1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(4, 0, 2, 0) == 2); } void TestAccessInvalidFluenceComponentIndex() { #ifdef _DEBUG m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); bool caughtException = false; try { double unusedValue = m_ComposedVolume->GetFluenceValue(0, 1, 2, 300); unusedValue = 0; } - catch (mitk::Exception e) + catch (const mitk::Exception e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); #endif } void TestAccessInvalidFluenceComponentForYOffset() { bool caughtException = false; try { m_ComposedVolume->GetYOffsetForFluenceComponentInPixels(0); } - catch (mitk::Exception e) + catch (const mitk::Exception &e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); } void tearDown() override { m_ComposedVolume = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticComposedVolume) diff --git a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp index 81583cbeff..8b1c524976 100644 --- a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp +++ b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp @@ -1,490 +1,490 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCorrectorAlgorithm.h" #include "mitkContourUtils.h" #include "mitkITKImageImport.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkImageDataItem.h" #include #include "itkCastImageFilter.h" #include "itkImageDuplicator.h" #include "itkImageRegionIterator.h" mitk::CorrectorAlgorithm::CorrectorAlgorithm() : ImageToImageFilter(), m_FillColor(1), m_EraseColor(0) { } mitk::CorrectorAlgorithm::~CorrectorAlgorithm() { } template void ConvertBackToCorrectPixelType( itk::Image *, mitk::Image::Pointer target, itk::Image::Pointer segmentationPixelTypeImage) { typedef itk::Image InputImageType; typedef itk::Image OutputImageType; typedef itk::CastImageFilter CastImageFilterType; typename CastImageFilterType::Pointer castImageFilter = CastImageFilterType::New(); castImageFilter->SetInput(segmentationPixelTypeImage); castImageFilter->Update(); typename OutputImageType::Pointer tempItkImage = castImageFilter->GetOutput(); tempItkImage->DisconnectPipeline(); mitk::CastToMitkImage(tempItkImage, target); } void mitk::CorrectorAlgorithm::GenerateData() { Image::Pointer inputImage = ImageToImageFilter::GetInput(0); if (inputImage.IsNull() || inputImage->GetDimension() != 2) { itkExceptionMacro("CorrectorAlgorithm needs a 2D image as input."); } if (m_Contour.IsNull()) { itkExceptionMacro("CorrectorAlgorithm needs a Contour object as input."); } // copy the input (since m_WorkingImage will be changed later) m_WorkingImage = inputImage; TimeGeometry::Pointer originalGeometry = nullptr; if (inputImage->GetTimeGeometry()) { originalGeometry = inputImage->GetTimeGeometry()->Clone(); m_WorkingImage->SetTimeGeometry(originalGeometry); } else { itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy."); } Image::Pointer temporarySlice; // Convert to DefaultSegmentationDataType (because TobiasHeimannCorrectionAlgorithm relys on that data type) { itk::Image::Pointer correctPixelTypeImage; CastToItkImage(m_WorkingImage, correctPixelTypeImage); assert(correctPixelTypeImage.IsNotNull()); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 // && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image::DirectionType imageDirection; imageDirection.SetIdentity(); // correctPixelTypeImage->SetDirection(imageDirection); temporarySlice = this->GetOutput(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); // m_FillColor = 1; m_EraseColor = 0; ImprovedHeimannCorrectionAlgorithm(correctPixelTypeImage); // this is suboptimal, needs to be kept synchronous to DefaultSegmentationDataType if (inputImage->GetChannelDescriptor().GetPixelType().GetComponentType() == itk::ImageIOBase::USHORT) { // the cast at the beginning did not copy the data CastToMitkImage(correctPixelTypeImage, temporarySlice); } else { // it did copy the data and cast the pixel type AccessByItk_n(m_WorkingImage, ConvertBackToCorrectPixelType, (temporarySlice, correctPixelTypeImage)); } } temporarySlice->SetTimeGeometry(originalGeometry); } template itk::Index<2> mitk::CorrectorAlgorithm::ensureIndexInImage(ScalarType i0, ScalarType i1) { itk::Index<2> toReturn; itk::Size<5> size = m_WorkingImage->GetLargestPossibleRegion().GetSize(); toReturn[0] = std::min((ScalarType)(size[0] - 1), std::max((ScalarType)0.0, i0)); toReturn[1] = std::min((ScalarType)(size[1] - 1), std::max((ScalarType)0.0, i1)); return toReturn; } bool mitk::CorrectorAlgorithm::ImprovedHeimannCorrectionAlgorithm( itk::Image::Pointer pic) { /*! Some documentation (not by the original author) TobiasHeimannCorrectionAlgorithm will be called, when the user has finished drawing a freehand line. There should be different results, depending on the line's properties: 1. Without any prior segmentation, the start point and the end point of the drawn line will be connected to a contour and the area enclosed by the contour will be marked as segmentation. 2. When the whole line is inside a segmentation, start and end point will be connected to a contour and the area of this contour will be subtracted from the segmentation. 3. When the line starts inside a segmentation and ends outside with only a single transition from segmentation to no-segmentation, nothing will happen. 4. When there are multiple transitions between inside-segmentation and outside-segmentation, the line will be divided in so called segments. Each segment is either fully inside or fully outside a segmentation. When it is inside a segmentation, its enclosed area will be subtracted from the segmentation. When the segment is outside a segmentation, its enclosed area it will be added to the segmentation. The algorithm is described in full length in Tobias Heimann's diploma thesis (MBI Technical Report 145, p. 37 - 40). */ ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice(m_WorkingImage, m_Contour, true, false); if (projectedContour.IsNull() || projectedContour->GetNumberOfVertices() < 2) return false; // Read the first point of the contour auto contourIter = projectedContour->Begin(); if (contourIter == projectedContour->End()) return false; itk::Index<2> previousIndex; previousIndex = ensureIndexInImage((*contourIter)->Coordinates[0], (*contourIter)->Coordinates[1]); ++contourIter; int currentColor = (pic->GetPixel(previousIndex) == m_FillColor); TSegData currentSegment; int countOfSegments = 1; bool firstSegment = true; auto contourEnd = projectedContour->End(); for (; contourIter != contourEnd; ++contourIter) { // Get current point itk::Index<2> currentIndex; currentIndex = ensureIndexInImage((*contourIter)->Coordinates[0] + 0.5, (*contourIter)->Coordinates[1] + 0.5); // Calculate length and slope double slopeX = currentIndex[0] - previousIndex[0]; double slopeY = currentIndex[1] - previousIndex[1]; double length = std::sqrt(slopeX * slopeX + slopeY * slopeY); double deltaX = slopeX / length; double deltaY = slopeY / length; for (double i = 0; i <= length && length > 0; i += 1) { itk::Index<2> temporaryIndex; temporaryIndex = ensureIndexInImage(previousIndex[0] + deltaX * i, previousIndex[1] + deltaY * i); if (!pic->GetLargestPossibleRegion().IsInside(temporaryIndex)) continue; if ((pic->GetPixel(temporaryIndex) == m_FillColor) != currentColor) { currentSegment.points.push_back(temporaryIndex); if (!firstSegment) { ModifySegment(currentSegment, pic); } else { firstSegment = false; } currentSegment = TSegData(); ++countOfSegments; currentColor = (pic->GetPixel(temporaryIndex) == m_FillColor); } currentSegment.points.push_back(temporaryIndex); } previousIndex = currentIndex; } return true; } void mitk::CorrectorAlgorithm::ColorSegment( const mitk::CorrectorAlgorithm::TSegData &segment, itk::Image::Pointer pic) { int colorMode = (pic->GetPixel(segment.points[0]) == m_FillColor); int color = 0; if (colorMode) color = m_EraseColor; else color = m_FillColor; std::vector>::const_iterator indexIterator; std::vector>::const_iterator indexEnd; indexIterator = segment.points.begin(); indexEnd = segment.points.end(); for (; indexIterator != indexEnd; ++indexIterator) { pic->SetPixel(*indexIterator, color); } } itk::Image::Pointer mitk::CorrectorAlgorithm::CloneImage( itk::Image::Pointer pic) { typedef itk::Image ItkImageType; typedef itk::ImageDuplicator DuplicatorType; DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(pic); duplicator->Update(); return duplicator->GetOutput(); } itk::Index<2> mitk::CorrectorAlgorithm::GetFirstPoint( const mitk::CorrectorAlgorithm::TSegData &segment, itk::Image::Pointer pic) { int colorMode = (pic->GetPixel(segment.points[0]) == m_FillColor); std::vector>::const_iterator indexIterator; std::vector>::const_iterator indexEnd; indexIterator = segment.points.begin(); indexEnd = segment.points.end(); itk::Index<2> index; for (; indexIterator != indexEnd; ++indexIterator) { for (int xOffset = -1; xOffset < 2; ++xOffset) { for (int yOffset = -1; yOffset < 2; ++yOffset) { index = ensureIndexInImage((*indexIterator)[0] - xOffset, (*indexIterator)[1] - yOffset); if ((pic->GetPixel(index) == m_FillColor) != colorMode) { return index; } } } } mitkThrow() << "No Starting point is found next to the curve."; } std::vector> mitk::CorrectorAlgorithm::FindSeedPoints( const mitk::CorrectorAlgorithm::TSegData &segment, itk::Image::Pointer pic) { typedef itk::Image::Pointer ItkImagePointerType; std::vector> seedPoints; try { itk::Index<2> firstPoint = GetFirstPoint(segment, pic); seedPoints.push_back(firstPoint); } - catch (mitk::Exception e) + catch (const mitk::Exception& e) { return seedPoints; } if (segment.points.size() < 4) return seedPoints; std::vector>::const_iterator indexIterator; std::vector>::const_iterator indexEnd; indexIterator = segment.points.begin(); indexEnd = segment.points.end(); ItkImagePointerType listOfPoints = CloneImage(pic); listOfPoints->FillBuffer(0); listOfPoints->SetPixel(seedPoints[0], 1); for (; indexIterator != indexEnd; ++indexIterator) { listOfPoints->SetPixel(*indexIterator, 2); } indexIterator = segment.points.begin(); indexIterator++; indexIterator++; indexEnd--; indexEnd--; for (; indexIterator != indexEnd; ++indexIterator) { bool pointFound = true; while (pointFound) { pointFound = false; itk::Index<2> index; itk::Index<2> index2; for (int xOffset = -1; xOffset < 2; ++xOffset) { for (int yOffset = -1; yOffset < 2; ++yOffset) { index = ensureIndexInImage((*indexIterator)[0] - xOffset, (*indexIterator)[1] - yOffset); index2 = index; if (listOfPoints->GetPixel(index2) > 0) continue; index[0] = index[0] - 1; index = ensureIndexInImage(index[0], index[1]); if (listOfPoints->GetPixel(index) == 1) { pointFound = true; seedPoints.push_back(index2); listOfPoints->SetPixel(index2, 1); continue; } index[0] = index[0] + 2; index = ensureIndexInImage(index[0], index[1]); if (listOfPoints->GetPixel(index) == 1) { pointFound = true; seedPoints.push_back(index2); listOfPoints->SetPixel(index2, 1); continue; } index[0] = index[0] - 1; index[1] = index[1] - 1; index = ensureIndexInImage(index[0], index[1]); if (listOfPoints->GetPixel(index) == 1) { pointFound = true; seedPoints.push_back(index2); listOfPoints->SetPixel(index2, 1); continue; } index[1] = index[1] + 2; index = ensureIndexInImage(index[0], index[1]); if (listOfPoints->GetPixel(index) == 1) { pointFound = true; seedPoints.push_back(index2); listOfPoints->SetPixel(index2, 1); continue; } } } } } return seedPoints; } int mitk::CorrectorAlgorithm::FillRegion( const std::vector> &seedPoints, itk::Image::Pointer pic) { int numberOfPixel = 0; int mode = (pic->GetPixel(seedPoints[0]) == m_FillColor); int drawColor = m_FillColor; if (mode) { drawColor = m_EraseColor; } std::vector> workPoints; workPoints = seedPoints; // workPoints.push_back(seedPoints[0]); while (workPoints.size() > 0) { itk::Index<2> currentIndex = workPoints.back(); workPoints.pop_back(); if ((pic->GetPixel(currentIndex) == m_FillColor) == mode) ++numberOfPixel; pic->SetPixel(currentIndex, drawColor); currentIndex = ensureIndexInImage(currentIndex[0] - 1, currentIndex[1]); if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == m_FillColor) == mode) workPoints.push_back(currentIndex); currentIndex = ensureIndexInImage(currentIndex[0] + 2, currentIndex[1]); if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == m_FillColor) == mode) workPoints.push_back(currentIndex); currentIndex = ensureIndexInImage(currentIndex[0] - 1, currentIndex[1] - 1); if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == m_FillColor) == mode) workPoints.push_back(currentIndex); currentIndex = ensureIndexInImage(currentIndex[0], currentIndex[1] + 2); if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == m_FillColor) == mode) workPoints.push_back(currentIndex); } return numberOfPixel; } void mitk::CorrectorAlgorithm::OverwriteImage( itk::Image::Pointer source, itk::Image::Pointer target) { typedef itk::Image ItkImageType; typedef itk::ImageRegionIterator ImageIteratorType; ImageIteratorType sourceIter(source, source->GetLargestPossibleRegion()); ImageIteratorType targetIter(target, target->GetLargestPossibleRegion()); while (!sourceIter.IsAtEnd()) { targetIter.Set(sourceIter.Get()); ++sourceIter; ++targetIter; } } bool mitk::CorrectorAlgorithm::ModifySegment(const TSegData &segment, itk::Image::Pointer pic) { typedef itk::Image::Pointer ItkImagePointerType; ItkImagePointerType firstSideImage = CloneImage(pic); ColorSegment(segment, firstSideImage); ItkImagePointerType secondSideImage = CloneImage(firstSideImage); std::vector> seedPoints = FindSeedPoints(segment, firstSideImage); if (seedPoints.size() < 1) return false; int firstSidePixel = FillRegion(seedPoints, firstSideImage); std::vector> secondSeedPoints = FindSeedPoints(segment, firstSideImage); if (secondSeedPoints.size() < 1) return false; int secondSidePixel = FillRegion(secondSeedPoints, secondSideImage); if (firstSidePixel < secondSidePixel) { OverwriteImage(firstSideImage, pic); } else { OverwriteImage(secondSideImage, pic); } return true; } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp index 293eee4487..cbc7025dbb 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp @@ -1,1356 +1,1356 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkSlicesInterpolator.h" #include "QmitkSelectableGLWidget.h" #include "QmitkStdMultiWidget.h" #include "mitkApplyDiffImageOperation.h" #include "mitkColorProperty.h" #include "mitkCoreObjectFactory.h" #include "mitkDiffImageApplier.h" #include "mitkInteractionConst.h" #include "mitkLevelWindowProperty.h" #include "mitkOperationEvent.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkProgressBar.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkSegTool2D.h" #include "mitkSliceNavigationController.h" #include "mitkSurfaceToImageFilter.h" #include "mitkToolManager.h" #include "mitkUndoController.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f}; const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; foreach (mitk::SliceNavigationController *slicer, m_ControllerToDeleteObserverTag.keys()) { actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetViewDirectionAsString()), nullptr)] = slicer; } return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/) : QWidget(parent), // ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator(mitk::SegmentationInterpolationController::New()), m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()), m_ToolManager(nullptr), m_Initialized(false), m_LastSNC(nullptr), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false), m_FirstRun(true) { m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_EdgeDetector = mitk::FeatureBasedEdgeDetectionFilter::New(); m_PointScorer = mitk::PointCloudScoringFilter::New(); m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation->addItem("Disabled"); m_CmbInterpolation->addItem("2-Dimensional"); m_CmbInterpolation->addItem("3-Dimensional"); vboxLayout->addWidget(m_CmbInterpolation); m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply2D); m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApplyForAllSlices2D); m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply3D); m_BtnSuggestPlane = new QPushButton("Suggest a plane", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnSuggestPlane); m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnReinit3DInterpolation); m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_ChkShowPositionNodes); this->HideAllInterpolationControls(); connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int))); connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked())); connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); connect(m_BtnSuggestPlane, SIGNAL(clicked()), this, SLOT(OnSuggestPlaneClicked())); connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation())); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode); this->setLayout(layout); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged); InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged); SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2); // feedback node and its visualization properties m_FeedbackNode = mitk::DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(m_FeedbackNode); m_FeedbackNode->SetProperty("binary", mitk::BoolProperty::New(true)); m_FeedbackNode->SetProperty("outline binary", mitk::BoolProperty::New(true)); m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0)); m_FeedbackNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false)); m_FeedbackNode->SetProperty("layer", mitk::IntProperty::New(20)); m_FeedbackNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(0, 1))); m_FeedbackNode->SetProperty("name", mitk::StringProperty::New("Interpolation feedback")); m_FeedbackNode->SetProperty("opacity", mitk::FloatProperty::New(0.8)); m_FeedbackNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback")); m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f)); m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode = mitk::DataNode::New(); m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0)); m_3DContourNode->SetProperty("hidden object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty("name", mitk::StringProperty::New("Drawn Contours")); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); QWidget::setContentsMargins(0, 0, 0, 0); if (QWidget::layout() != nullptr) { QWidget::layout()->setContentsMargins(0, 0, 0, 0); } // For running 3D Interpolation in background // create a QFuture and a QFutureWatcher connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer())); m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor())); } void QmitkSlicesInterpolator::SetDataStorage(mitk::DataStorage::Pointer storage) { if (m_DataStorage == storage) { return; } if (m_DataStorage.IsNotNull()) { m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkSlicesInterpolator::NodeRemoved) ); } m_DataStorage = storage; m_SurfaceInterpolator->SetDataStorage(storage); if (m_DataStorage.IsNotNull()) { m_DataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1(this, &QmitkSlicesInterpolator::NodeRemoved) ); } } mitk::DataStorage *QmitkSlicesInterpolator::GetDataStorage() { if (m_DataStorage.IsNotNull()) { return m_DataStorage; } else { return nullptr; } } void QmitkSlicesInterpolator::Initialize(mitk::ToolManager *toolManager, const QList &controllers) { Q_ASSERT(!controllers.empty()); if (m_Initialized) { // remove old observers Uninitialize(); } m_ToolManager = toolManager; if (m_ToolManager) { // set enabled only if a segmentation is selected mitk::DataNode *node = m_ToolManager->GetWorkingData(0); QWidget::setEnabled(node != nullptr); // react whenever the set of selected segmentation changes m_ToolManager->WorkingDataChanged += mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified); // connect to the slice navigation controller. after each change, call the interpolator foreach (mitk::SliceNavigationController *slicer, controllers) { // Has to be initialized m_LastSNC = slicer; m_TimeStep.insert(slicer, slicer->GetTime()->GetPos()); itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted); m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand)); itk::MemberCommand::Pointer timeChangedCommand = itk::MemberCommand::New(); timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged); m_ControllerToTimeObserverTag.insert( slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(nullptr, 0), timeChangedCommand)); itk::MemberCommand::Pointer sliceChangedCommand = itk::MemberCommand::New(); sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged); m_ControllerToSliceObserverTag.insert( slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand)); } ACTION_TO_SLICEDIMENSION = createActionToSliceDimension(); } m_Initialized = true; } void QmitkSlicesInterpolator::Uninitialize() { if (m_ToolManager.IsNotNull()) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified); } foreach (mitk::SliceNavigationController *slicer, m_ControllerToSliceObserverTag.keys()) { slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer)); } ACTION_TO_SLICEDIMENSION.clear(); m_ToolManager = nullptr; m_Initialized = false; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_Initialized) { // remove old observers Uninitialize(); } WaitForFutures(); if (m_DataStorage.IsNotNull()) { m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkSlicesInterpolator::NodeRemoved) ); if (m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); } // remove observer m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag); m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag); delete m_Timer; } /** External enableization... */ void QmitkSlicesInterpolator::setEnabled(bool enable) { QWidget::setEnabled(enable); // Set the gui elements of the different interpolation modi enabled if (enable) { if (m_2DInterpolationEnabled) { this->Show2DInterpolationControls(true); m_Interpolator->Activate2DInterpolation(true); } else if (m_3DInterpolationEnabled) { this->Show3DInterpolationControls(true); this->Show3DInterpolationResult(true); } } // Set all gui elements of the interpolation disabled else { this->HideAllInterpolationControls(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); m_Interpolator->Activate2DInterpolation(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::HideAllInterpolationControls() { this->Show2DInterpolationControls(false); this->Show3DInterpolationControls(false); } void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show) { m_BtnApply2D->setVisible(show); m_BtnApplyForAllSlices2D->setVisible(show); } void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show) { m_BtnApply3D->setVisible(show); m_BtnSuggestPlane->setVisible(show); m_ChkShowPositionNodes->setVisible(show); m_BtnReinit3DInterpolation->setVisible(show); } void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index) { switch (index) { case 0: // Disabled m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation"); this->HideAllInterpolationControls(); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(false); this->Show3DInterpolationResult(false); m_Interpolator->Activate2DInterpolation(false); break; case 1: // 2D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show2DInterpolationControls(true); this->OnInterpolationActivated(true); this->On3DInterpolationActivated(false); m_Interpolator->Activate2DInterpolation(true); break; case 2: // 3D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show3DInterpolationControls(true); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(true); m_Interpolator->Activate2DInterpolation(false); break; default: MITK_ERROR << "Unknown interpolation method!"; m_CmbInterpolation->setCurrentIndex(0); break; } } void QmitkSlicesInterpolator::OnShowMarkers(bool state) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true))); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state)); } } void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified() { if (m_ToolManager->GetWorkingData(0) != nullptr) { m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); m_BtnReinit3DInterpolation->setEnabled(true); } else { // If no workingdata is set, remove the interpolation feedback this->GetDataStorage()->Remove(m_FeedbackNode); m_FeedbackNode->SetData(nullptr); this->GetDataStorage()->Remove(m_3DContourNode); m_3DContourNode->SetData(nullptr); this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode); m_InterpolatedSurfaceNode->SetData(nullptr); m_BtnReinit3DInterpolation->setEnabled(false); return; } // Updating the current selected segmentation for the 3D interpolation SetCurrentContourListID(); if (m_2DInterpolationEnabled) { OnInterpolationActivated(true); // re-initialize if needed } this->CheckSupportedImageDimension(); } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { } void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e) { // Check if we really have a GeometryTimeEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController *slicer = dynamic_cast(sender); Q_ASSERT(slicer); m_TimeStep[slicer] = slicer->GetTime()->GetPos(); m_SurfaceInterpolator->SetCurrentTimeStep(slicer->GetTime()->GetPos()); if (m_LastSNC == slicer) { slicer->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) { // Check whether we really have a GeometrySliceEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController *slicer = dynamic_cast(sender); if (TranslateAndInterpolateChangedSlice(e, slicer)) { slicer->GetRenderer()->RequestUpdate(); } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent &event = dynamic_cast(e); mitk::TimeGeometry *tsg = event.GetTimeGeometry(); if (tsg && m_TimeStep.contains(slicer)) { mitk::SlicedGeometry3D *slicedGeometry = dynamic_cast(tsg->GetGeometryForTimeStep(m_TimeStep[slicer]).GetPointer()); if (slicedGeometry) { m_LastSNC = slicer; mitk::PlaneGeometry *plane = dynamic_cast(slicedGeometry->GetPlaneGeometry(event.GetPos())); if (plane) Interpolate(plane, m_TimeStep[slicer], slicer); return true; } } } - catch (std::bad_cast) + catch (const std::bad_cast &) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane, unsigned int timeStep, mitk::SliceNavigationController *slicer) { if (m_ToolManager) { mitk::DataNode *node = m_ToolManager->GetWorkingData(0); if (node) { m_Segmentation = dynamic_cast(node->GetData()); if (m_Segmentation) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); // calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex); mitk::Image::Pointer interpolation = m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep); m_FeedbackNode->SetData(interpolation); m_LastSNC = slicer; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (interpolatedSurface.IsNotNull() && workingNode && workingNode->IsVisible( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) { m_BtnApply3D->setEnabled(true); m_BtnSuggestPlane->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); this->Show3DInterpolationResult(true); if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { m_DataStorage->Add(m_InterpolatedSurfaceNode); } if (!m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode, workingNode); } } else if (interpolatedSurface.IsNull()) { m_BtnApply3D->setEnabled(false); m_BtnSuggestPlane->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { this->Show3DInterpolationResult(false); } } m_BtnReinit3DInterpolation->setEnabled(true); foreach (mitk::SliceNavigationController *slicer, m_ControllerToTimeObserverTag.keys()) { slicer->GetRenderer()->RequestUpdate(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { // Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk // reslicer vtkSmartPointer reslice = vtkSmartPointer::New(); // Set slice as input mitk::Image::Pointer slice = dynamic_cast(m_FeedbackNode->GetData()); reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageAccessor(slice)->GetVtkImageData()); // set overwrite mode to true to write back to the image volume reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); extractor->SetInput(m_Segmentation); unsigned int timestep = m_LastSNC->GetTime()->GetPos(); extractor->SetTimeStep(timestep); extractor->SetWorldGeometry(m_LastSNC->GetCurrentPlaneGeometry()); extractor->SetVtkOutputRequest(true); extractor->SetResliceTransformByGeometry(m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep(timestep)); extractor->Modified(); extractor->Update(); // the image was modified within the pipeline, but not marked so m_Segmentation->Modified(); m_Segmentation->GetVtkImageData()->Modified(); m_FeedbackNode->SetData(nullptr); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController *slicer) { /* * What exactly is done here: * 1. We create an empty diff image for the current segmentation * 2. All interpolated slices are written into the diff image * 3. Then the diffimage is applied to the original segmentation */ if (m_Segmentation) { mitk::Image::Pointer image3D = m_Segmentation; unsigned int timeStep(slicer->GetTime()->GetPos()); if (m_Segmentation->GetDimension() == 4) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(m_Segmentation); timeSelector->SetTimeNr(timeStep); timeSelector->Update(); image3D = timeSelector->GetOutput(); } // create a empty diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize(image3D); // Create scope for ImageWriteAccessor so that the accessor is destroyed // after the image is initialized. Otherwise later image access will lead to an error { mitk::ImageWriteAccessor imAccess(diffImage); // Set all pixels to zero mitk::PixelType pixelType(mitk::MakeScalarPixelType()); // For legacy purpose support former pixel type of segmentations (before multilabel) if (m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) { pixelType = mitk::MakeScalarPixelType(); } memset(imAccess.GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2)); } // Since we need to shift the plane it must be clone so that the original plane isn't altered mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone(); int sliceDimension(-1); int sliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, reslicePlane, sliceDimension, sliceIndex); unsigned int zslices = m_Segmentation->GetDimension(sliceDimension); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); mitk::Point3D origin = reslicePlane->GetOrigin(); unsigned int totalChangedSlices(0); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { // Transforming the current origin of the reslice plane // so that it matches the one of the next slice m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin); origin[sliceDimension] = sliceIndex; m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin); reslicePlane->SetOrigin(origin); // Set the slice as 'input' mitk::Image::Pointer interpolation = m_Interpolator->Interpolate(sliceDimension, sliceIndex, reslicePlane, timeStep); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { // Setting up the reslicing pipeline which allows us to write the interpolation results back into // the image volume vtkSmartPointer reslice = vtkSmartPointer::New(); // set overwrite mode to true to write back to the image volume reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData()); reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer diffslicewriter = mitk::ExtractSliceFilter::New(reslice); diffslicewriter->SetInput(diffImage); diffslicewriter->SetTimeStep(0); diffslicewriter->SetWorldGeometry(reslicePlane); diffslicewriter->SetVtkOutputRequest(true); diffslicewriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0)); diffslicewriter->Modified(); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (totalChangedSlices > 0) { // store undo stack items if (true) { // create do/undo operations mitk::ApplyDiffImageOperation *doOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep); mitk::ApplyDiffImageOperation *undoOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep); undoOp->SetFactor(-1.0); std::stringstream comment; comment << "Confirm all interpolations (" << totalChangedSlices << ")"; mitk::OperationEvent *undoStackItem = new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str()); mitk::OperationEvent::IncCurrGroupEventId(); mitk::OperationEvent::IncCurrObjectEventId(); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem); // acutally apply the changes here to the original image mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation(doOp); } } m_FeedbackNode->SetData(nullptr); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController *slicer) { // this redirect is for calling from outside if (slicer == nullptr) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations(slicer); } void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for (it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++) orientationPopup.addAction(it->first); connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *))); orientationPopup.exec(QCursor::pos()); } void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { mitk::DataNode *segmentationNode = m_ToolManager->GetWorkingData(0); mitk::Image *currSeg = dynamic_cast(segmentationNode->GetData()); mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); if (currSeg->GetPixelType().GetComponentType() == itk::ImageIOBase::USHORT) s2iFilter->SetUShortBinaryPixelType(true); s2iFilter->SetInput(dynamic_cast(m_InterpolatedSurfaceNode->GetData())); // check if ToolManager holds valid ReferenceData if (m_ToolManager->GetReferenceData(0) == nullptr || m_ToolManager->GetWorkingData(0) == nullptr) { return; } s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::Image::Pointer newSeg = s2iFilter->GetOutput(); unsigned int timestep = m_LastSNC->GetTime()->GetPos(); mitk::ImageReadAccessor readAccess(newSeg, newSeg->GetVolumeData(timestep)); const void *cPointer = readAccess.GetData(); if (currSeg && cPointer) { currSeg->SetVolume(cPointer, timestep, 0); } else { return; } m_CmbInterpolation->setCurrentIndex(0); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::DataNode::Pointer segSurface = mitk::DataNode::New(); float rgb[3]; segmentationNode->GetColor(rgb); segSurface->SetColor(rgb); segSurface->SetData(m_InterpolatedSurfaceNode->GetData()); std::stringstream stream; stream << segmentationNode->GetName(); stream << "_"; stream << "3D-interpolation"; segSurface->SetName(stream.str()); segSurface->SetProperty("opacity", mitk::FloatProperty::New(0.7)); segSurface->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(true)); segSurface->SetProperty("3DInterpolationResult", mitk::BoolProperty::New(true)); segSurface->SetVisibility(false); m_DataStorage->Add(segSurface, segmentationNode); this->Show3DInterpolationResult(false); } } void ::QmitkSlicesInterpolator::OnSuggestPlaneClicked() { if (m_PlaneWatcher.isRunning()) m_PlaneWatcher.waitForFinished(); m_PlaneFuture = QtConcurrent::run(this, &QmitkSlicesInterpolator::RunPlaneSuggestion); m_PlaneWatcher.setFuture(m_PlaneFuture); } void ::QmitkSlicesInterpolator::RunPlaneSuggestion() { if (m_FirstRun) mitk::ProgressBar::GetInstance()->AddStepsToDo(7); else mitk::ProgressBar::GetInstance()->AddStepsToDo(3); m_EdgeDetector->SetSegmentationMask(m_Segmentation); m_EdgeDetector->SetInput(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); m_EdgeDetector->Update(); mitk::UnstructuredGrid::Pointer uGrid = mitk::UnstructuredGrid::New(); uGrid->SetVtkUnstructuredGrid(m_EdgeDetector->GetOutput()->GetVtkUnstructuredGrid()); mitk::ProgressBar::GetInstance()->Progress(); mitk::Surface::Pointer surface = dynamic_cast(m_InterpolatedSurfaceNode->GetData()); vtkSmartPointer vtkpoly = surface->GetVtkPolyData(); vtkSmartPointer vtkpoints = vtkpoly->GetPoints(); vtkSmartPointer vGrid = vtkSmartPointer::New(); vtkSmartPointer verts = vtkSmartPointer::New(); verts->GetPointIds()->SetNumberOfIds(vtkpoints->GetNumberOfPoints()); for (int i = 0; i < vtkpoints->GetNumberOfPoints(); i++) { verts->GetPointIds()->SetId(i, i); } vGrid->Allocate(1); vGrid->InsertNextCell(verts->GetCellType(), verts->GetPointIds()); vGrid->SetPoints(vtkpoints); mitk::UnstructuredGrid::Pointer interpolationGrid = mitk::UnstructuredGrid::New(); interpolationGrid->SetVtkUnstructuredGrid(vGrid); m_PointScorer->SetInput(0, uGrid); m_PointScorer->SetInput(1, interpolationGrid); m_PointScorer->Update(); mitk::UnstructuredGrid::Pointer scoredGrid = mitk::UnstructuredGrid::New(); scoredGrid = m_PointScorer->GetOutput(); mitk::ProgressBar::GetInstance()->Progress(); double spacing = mitk::SurfaceInterpolationController::GetInstance()->GetDistanceImageSpacing(); mitk::UnstructuredGridClusteringFilter::Pointer clusterFilter = mitk::UnstructuredGridClusteringFilter::New(); clusterFilter->SetInput(scoredGrid); clusterFilter->SetMeshing(false); clusterFilter->SetMinPts(4); clusterFilter->Seteps(spacing); clusterFilter->Update(); mitk::ProgressBar::GetInstance()->Progress(); // Create plane suggestion mitk::BaseRenderer::Pointer br = mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")); mitk::PlaneProposer planeProposer; std::vector grids = clusterFilter->GetAllClusters(); planeProposer.SetUnstructuredGrids(grids); mitk::SliceNavigationController::Pointer snc = br->GetSliceNavigationController(); planeProposer.SetSliceNavigationController(snc); planeProposer.SetUseDistances(true); try { planeProposer.CreatePlaneInfo(); } - catch (mitk::Exception &e) + catch (const mitk::Exception &e) { MITK_ERROR << e.what(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_FirstRun = false; } void QmitkSlicesInterpolator::OnReinit3DInterpolation() { mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("3DContourContainer", mitk::BoolProperty::New(true)); mitk::DataStorage::SetOfObjects::ConstPointer contourNodes = m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred); if (contourNodes->Size() != 0) { m_BtnApply3D->setEnabled(true); m_3DContourNode = contourNodes->at(0); mitk::Surface::Pointer contours = dynamic_cast(m_3DContourNode->GetData()); if (contours) mitk::SurfaceInterpolationController::GetInstance()->ReinitializeInterpolation(contours); m_BtnReinit3DInterpolation->setEnabled(false); } else { m_BtnApply3D->setEnabled(false); QMessageBox errorInfo; errorInfo.setWindowTitle("Reinitialize surface interpolation"); errorInfo.setIcon(QMessageBox::Information); errorInfo.setText("No contours available for the selected segmentation!"); errorInfo.exec(); } } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction *action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find(action); if (iter != ACTION_TO_SLICEDIMENSION.end()) { mitk::SliceNavigationController *slicer = iter->second; AcceptAllInterpolations(slicer); } } catch (...) { /* Showing message box with possible memory error */ QMessageBox errorInfo; errorInfo.setWindowTitle("Interpolation Process"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!"); errorInfo.exec(); // additional error message on std::cerr std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl; } } void QmitkSlicesInterpolator::OnInterpolationActivated(bool on) { m_2DInterpolationEnabled = on; try { if (m_DataStorage.IsNotNull()) { if (on && !m_DataStorage->Exists(m_FeedbackNode)) { m_DataStorage->Add(m_FeedbackNode); } } } catch (...) { // don't care (double add/remove) } if (m_ToolManager) { mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0); QWidget::setEnabled(workingNode != nullptr); m_BtnApply2D->setEnabled(on); m_FeedbackNode->SetVisibility(on); if (!on) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } if (workingNode) { mitk::Image *segmentation = dynamic_cast(workingNode->GetData()); if (segmentation) { m_Interpolator->SetSegmentationVolume(segmentation); if (referenceNode) { mitk::Image *referenceImage = dynamic_cast(referenceNode->GetData()); m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr } } } } UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::Run3DInterpolation() { m_SurfaceInterpolator->Interpolate(); } void QmitkSlicesInterpolator::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSlicesInterpolator::StopUpdateInterpolationTimer() { m_Timer->stop(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); mitk::RenderingManager::GetInstance()->RequestUpdate( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); if (currentColor[2] == SURFACE_COLOR_RGB[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 1.0f)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; this->CheckSupportedImageDimension(); try { if (m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult", isInterpolationResult); mitk::NodePredicateAnd::Pointer pred = mitk::NodePredicateAnd::New( mitk::NodePredicateProperty::New("3DInterpolationResult", mitk::BoolProperty::New(true)), mitk::NodePredicateDataType::New("Surface")); mitk::DataStorage::SetOfObjects::ConstPointer interpolationResults = m_DataStorage->GetDerivations(workingNode, pred); for (unsigned int i = 0; i < interpolationResults->Size(); ++i) { mitk::DataNode::Pointer currNode = interpolationResults->at(i); if (currNode.IsNotNull()) m_DataStorage->Remove(currNode); } if ((workingNode->IsVisible( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult && m_3DInterpolationEnabled) { int ret = QMessageBox::Yes; if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5) { QMessageBox msgBox; msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!"); msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?"); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); ret = msgBox.exec(); } if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); if (ret == QMessageBox::Yes) { m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { m_CmbInterpolation->setCurrentIndex(0); } } else if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled); } } else { QWidget::setEnabled(false); m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled); } } if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled); } } catch (...) { MITK_ERROR << "Error with 3D surface interpolation!"; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::EnableInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated OnInterpolationActivated(on); } void QmitkSlicesInterpolator::Enable3DInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated On3DInterpolationActivated(on); } void QmitkSlicesInterpolator::UpdateVisibleSuggestion() { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/) { if (m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } void QmitkSlicesInterpolator::SetCurrentContourListID() { // New ContourList = hide current interpolation Show3DInterpolationResult(false); if (m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC) { mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult", isInterpolationResult); if (!isInterpolationResult) { QWidget::setEnabled(true); // In case the time is not valid use 0 to access the time geometry of the working node unsigned int time_position = 0; if (m_LastSNC->GetTime() != nullptr) time_position = m_LastSNC->GetTime()->GetPos(); mitk::Vector3D spacing = workingNode->GetData()->GetGeometry(time_position)->GetSpacing(); double minSpacing(100); double maxSpacing(0); for (int i = 0; i < 3; i++) { if (spacing[i] < minSpacing) { minSpacing = spacing[i]; } if (spacing[i] > maxSpacing) { maxSpacing = spacing[i]; } } m_SurfaceInterpolator->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); mitk::Image *segmentationImage = dynamic_cast(workingNode->GetData()); /*if (segmentationImage->GetDimension() == 3) {*/ m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage); m_SurfaceInterpolator->SetCurrentTimeStep(time_position); //} /*else MITK_INFO<<"3D Interpolation is only supported for 3D images at the moment!";*/ if (m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } } else { QWidget::setEnabled(false); } } } void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status) { if (m_InterpolatedSurfaceNode.IsNotNull()) m_InterpolatedSurfaceNode->SetVisibility(status); if (m_3DContourNode.IsNotNull()) m_3DContourNode->SetVisibility( status, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::CheckSupportedImageDimension() { if (m_ToolManager->GetWorkingData(0)) m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); /*if (m_3DInterpolationEnabled && m_Segmentation && m_Segmentation->GetDimension() != 3) { QMessageBox info; info.setWindowTitle("3D Interpolation Process"); info.setIcon(QMessageBox::Information); info.setText("3D Interpolation is only supported for 3D images at the moment!"); info.exec(); m_CmbInterpolation->setCurrentIndex(0); }*/ } void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject & /*e*/) { // Don't know how to avoid const_cast here?! mitk::SliceNavigationController *slicer = dynamic_cast(const_cast(sender)); if (slicer) { m_ControllerToTimeObserverTag.remove(slicer); m_ControllerToSliceObserverTag.remove(slicer); m_ControllerToDeleteObserverTag.remove(slicer); } } void QmitkSlicesInterpolator::WaitForFutures() { if (m_Watcher.isRunning()) { m_Watcher.waitForFinished(); } if (m_PlaneWatcher.isRunning()) { m_PlaneWatcher.waitForFinished(); } } void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node) { if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) || node == m_3DContourNode || node == m_FeedbackNode || node == m_InterpolatedSurfaceNode) { WaitForFutures(); } } diff --git a/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp b/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp index f3c324ed72..efefbcd261 100644 --- a/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp +++ b/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp @@ -1,347 +1,347 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkComputeContourSetNormalsFilter.h" #include "mitkIOUtil.h" #include "mitkImagePixelReadAccessor.h" mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter() : m_SegmentationBinaryImage(nullptr), m_MaxSpacing(5), m_NegativeNormalCounter(0), m_PositiveNormalCounter(0), m_UseProgressBar(false), m_ProgressStepSize(1) { mitk::Surface::Pointer output = mitk::Surface::New(); this->SetNthOutput(0, output.GetPointer()); } mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter() { } void mitk::ComputeContourSetNormalsFilter::GenerateData() { unsigned int numberOfInputs = this->GetNumberOfIndexedInputs(); // Iterating over each input for (unsigned int i = 0; i < numberOfInputs; i++) { // Getting the inputs polydata and polygons auto *currentSurface = this->GetInput(i); vtkPolyData *polyData = currentSurface->GetVtkPolyData(); vtkSmartPointer existingPolys = polyData->GetPolys(); vtkSmartPointer existingPoints = polyData->GetPoints(); existingPolys->InitTraversal(); vtkIdType *cell(nullptr); vtkIdType cellSize(0); // The array that contains all the vertex normals of the current polygon vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(polyData->GetNumberOfPoints()); // If the current contour is an inner contour then the direction is -1 // A contour lies inside another one if the pixel values in the direction of the normal is 1 m_NegativeNormalCounter = 0; m_PositiveNormalCounter = 0; vtkIdType offSet(0); // Iterating over each polygon for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);) { if (cellSize < 3) continue; // First we calculate the current polygon's normal double polygonNormal[3] = {0.0}; double p1[3]; double p2[3]; double v1[3]; double v2[3]; existingPoints->GetPoint(cell[0], p1); unsigned int index = cellSize * 0.5; existingPoints->GetPoint(cell[index], p2); v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; for (vtkIdType k = 2; k < cellSize; k++) { index = cellSize * 0.25; existingPoints->GetPoint(cell[index], p1); index = cellSize * 0.75; existingPoints->GetPoint(cell[index], p2); v2[0] = p2[0] - p1[0]; v2[1] = p2[1] - p1[1]; v2[2] = p2[2] - p1[2]; vtkMath::Cross(v1, v2, polygonNormal); if (vtkMath::Norm(polygonNormal) != 0) break; } vtkMath::Normalize(polygonNormal); // Now we start computing the normal for each vertex double vertexNormalTemp[3]; existingPoints->GetPoint(cell[0], p1); existingPoints->GetPoint(cell[1], p2); v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; vtkMath::Cross(v1, polygonNormal, vertexNormalTemp); vtkMath::Normalize(vertexNormalTemp); double vertexNormal[3]; for (vtkIdType j = 0; j < cellSize - 2; j++) { existingPoints->GetPoint(cell[j + 1], p1); existingPoints->GetPoint(cell[j + 2], p2); v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; vtkMath::Cross(v1, polygonNormal, vertexNormal); vtkMath::Normalize(vertexNormal); double finalNormal[3]; finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0]) * 0.5; finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1]) * 0.5; finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2]) * 0.5; vtkMath::Normalize(finalNormal); // Here we determine the direction of the normal if (m_SegmentationBinaryImage) { Point3D worldCoord; worldCoord[0] = p1[0] + finalNormal[0] * m_MaxSpacing; worldCoord[1] = p1[1] + finalNormal[1] * m_MaxSpacing; worldCoord[2] = p1[2] + finalNormal[2] * m_MaxSpacing; double val = 0.0; itk::Index<3> idx; m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx); try { if (m_SegmentationBinaryImage->GetImageDescriptor() ->GetChannelDescriptor() .GetPixelType() .GetComponentType() == itk::ImageIOBase::UCHAR) { mitk::ImagePixelReadAccessor readAccess(m_SegmentationBinaryImage); val = readAccess.GetPixelByIndexSafe(idx); } else if (m_SegmentationBinaryImage->GetImageDescriptor() ->GetChannelDescriptor() .GetPixelType() .GetComponentType() == itk::ImageIOBase::USHORT) { mitk::ImagePixelReadAccessor readAccess(m_SegmentationBinaryImage); val = readAccess.GetPixelByIndexSafe(idx); } } - catch (mitk::Exception e) + catch (const mitk::Exception &e) { // If value is outside the image's region ignore it MITK_WARN << e.what(); } if (val == 0.0) { // MITK_INFO << "val equals zero."; ++m_PositiveNormalCounter; } else { // MITK_INFO << "val does not equal zero."; ++m_NegativeNormalCounter; } } vertexNormalTemp[0] = vertexNormal[0]; vertexNormalTemp[1] = vertexNormal[1]; vertexNormalTemp[2] = vertexNormal[2]; vtkIdType id = cell[j + 1]; normals->SetTuple(id, finalNormal); } existingPoints->GetPoint(cell[0], p1); existingPoints->GetPoint(cell[1], p2); v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; vtkMath::Cross(v1, polygonNormal, vertexNormal); vtkMath::Normalize(vertexNormal); vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0]) * 0.5; vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1]) * 0.5; vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2]) * 0.5; vtkMath::Normalize(vertexNormal); vtkIdType id = cell[0]; normals->SetTuple(id, vertexNormal); id = cell[cellSize - 1]; normals->SetTuple(id, vertexNormal); if (m_NegativeNormalCounter > m_PositiveNormalCounter) { for (vtkIdType n = 0; n < cellSize; n++) { double normal[3]; normals->GetTuple(offSet + n, normal); normal[0] = (-1) * normal[0]; normal[1] = (-1) * normal[1]; normal[2] = (-1) * normal[2]; normals->SetTuple(offSet + n, normal); } } m_NegativeNormalCounter = 0; m_PositiveNormalCounter = 0; offSet += cellSize; } // end for all cells Surface::Pointer surface = this->GetOutput(i); surface->GetVtkPolyData()->GetCellData()->SetNormals(normals); } // end for all inputs // Setting progressbar if (this->m_UseProgressBar) mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize); } mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface() { // Just for debugging: vtkSmartPointer newPolyData = vtkSmartPointer::New(); vtkSmartPointer newLines = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); unsigned int idCounter(0); // Debug end for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++) { auto *currentSurface = this->GetOutput(i); vtkPolyData *polyData = currentSurface->GetVtkPolyData(); vtkSmartPointer currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals()); vtkSmartPointer existingPolys = polyData->GetPolys(); vtkSmartPointer existingPoints = polyData->GetPoints(); existingPolys->InitTraversal(); vtkIdType *cell(nullptr); vtkIdType cellSize(0); for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);) { for (vtkIdType j = 0; j < cellSize; j++) { double currentNormal[3]; currentCellNormals->GetTuple(cell[j], currentNormal); vtkSmartPointer line = vtkSmartPointer::New(); line->GetPointIds()->SetNumberOfIds(2); double newPoint[3]; double p0[3]; existingPoints->GetPoint(cell[j], p0); newPoint[0] = p0[0] + currentNormal[0]; newPoint[1] = p0[1] + currentNormal[1]; newPoint[2] = p0[2] + currentNormal[2]; line->GetPointIds()->SetId(0, idCounter); newPoints->InsertPoint(idCounter, p0); idCounter++; line->GetPointIds()->SetId(1, idCounter); newPoints->InsertPoint(idCounter, newPoint); idCounter++; newLines->InsertNextCell(line); } // end for all points } // end for all cells } // end for all outputs newPolyData->SetPoints(newPoints); newPolyData->SetLines(newLines); newPolyData->BuildCells(); mitk::Surface::Pointer surface = mitk::Surface::New(); surface->SetVtkPolyData(newPolyData); return surface; } void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing) { m_MaxSpacing = maxSpacing; } void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); } void mitk::ComputeContourSetNormalsFilter::Reset() { for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++) { this->PopBackInput(); } this->SetNumberOfIndexedInputs(0); this->SetNumberOfIndexedOutputs(0); mitk::Surface::Pointer output = mitk::Surface::New(); this->SetNthOutput(0, output.GetPointer()); } void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status) { this->m_UseProgressBar = status; } void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize) { this->m_ProgressStepSize = stepSize; } diff --git a/Modules/XNAT/src/QmitkXnatTreeModel.cpp b/Modules/XNAT/src/QmitkXnatTreeModel.cpp index c3acde60e3..a6603b64ca 100644 --- a/Modules/XNAT/src/QmitkXnatTreeModel.cpp +++ b/Modules/XNAT/src/QmitkXnatTreeModel.cpp @@ -1,316 +1,316 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkXnatTreeModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include QmitkXnatTreeModel::QmitkXnatTreeModel() : ctkXnatTreeModel() { } QModelIndexList QmitkXnatTreeModel::match( const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const { QModelIndexList result; uint matchType = flags & 0x0F; Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; bool recurse = flags & Qt::MatchRecursive; bool wrap = flags & Qt::MatchWrap; bool allHits = (hits == -1); QString text; // only convert to a string if it is needed QModelIndex p = parent(start); int from = start.row(); int to = rowCount(p); // iterates twice if wrapping for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) { QModelIndex idx = index(r, start.column(), p); if (!idx.isValid()) continue; QVariant v = data(idx, role); // QVariant based matching if (matchType == Qt::MatchExactly) { if (value != v) result.append(idx); } else { // QString based matching if (text.isEmpty()) // lazy conversion text = value.toString(); QString t = v.toString(); switch (matchType) { case Qt::MatchRegExp: if (!QRegExp(text, cs).exactMatch(t)) result.append(idx); break; case Qt::MatchWildcard: if (!QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t)) result.append(idx); break; case Qt::MatchStartsWith: if (!t.startsWith(text, cs)) result.append(idx); break; case Qt::MatchEndsWith: if (!t.endsWith(text, cs)) result.append(idx); break; case Qt::MatchFixedString: if (t.compare(text, cs) != 0) result.append(idx); break; case Qt::MatchContains: default: if (!t.contains(text, cs)) result.append(idx); } } if (recurse && hasChildren(idx)) { // search the hierarchy result += match(index(0, idx.column(), idx), role, (text.isEmpty() ? value : text), (allHits ? -1 : hits - result.count()), flags); } } // prepare for the next iteration from = 0; to = start.row(); } return result; } void QmitkXnatTreeModel::fetchMore(const QModelIndex &index) { try { ctkXnatTreeModel::fetchMore(index); } - catch (ctkRuntimeException e) + catch (const ctkRuntimeException& e) { QmitkHttpStatusCodeHandler::HandleErrorMessage(e.what()); emit Error(index); } } QVariant QmitkXnatTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (role == Qt::DecorationRole) { ctkXnatObject *xnatObject = this->xnatObject(index); QString path; if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-server.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-project.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-subject.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-experiment.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-folder.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-resource.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-folder.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-scan.png"; } else if (dynamic_cast(xnatObject)) { path = ":/xnat-module/xnat-file.png"; } return QIcon(path); } return ctkXnatTreeModel::data(index, role); } bool QmitkXnatTreeModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent) { if (action == Qt::IgnoreAction) return true; // Return true if data can be handled bool returnVal(false); if (data->hasFormat(QmitkMimeTypes::DataNodePtrs)) { returnVal = true; QList droppedNodes = QmitkMimeTypes::ToDataNodePtrList(data); ctkXnatObject *parentXnatObj = this->xnatObject(parent); emit ResourceDropped(droppedNodes, parentXnatObj, parent); } return returnVal; } Qt::DropActions QmitkXnatTreeModel::supportedDropActions() { return Qt::CopyAction; } Qt::ItemFlags QmitkXnatTreeModel::flags(const QModelIndex &index) const { Qt::ItemFlags defaultFlags = ctkXnatTreeModel::flags(index); if (index.isValid()) { bool droppingAllowed = dynamic_cast(this->xnatObject(index)) != nullptr; droppingAllowed |= dynamic_cast(this->xnatObject(index)) != nullptr; droppingAllowed |= dynamic_cast(this->xnatObject(index)) != nullptr; droppingAllowed |= dynamic_cast(this->xnatObject(index)) != nullptr; // No dropping at project, session or data model level allowed if (droppingAllowed) { return Qt::ItemIsDropEnabled | defaultFlags; } else { return defaultFlags; } } else return defaultFlags; } ctkXnatObject *QmitkXnatTreeModel::InternalGetXnatObjectFromUrl(const QString &xnatObjectType, const QString &url, ctkXnatObject *parent) { // 1. Find project int start = url.lastIndexOf(xnatObjectType); if (start == -1) return nullptr; start += xnatObjectType.length(); int length = url.indexOf("/", start); length -= start; parent->fetch(); QList children = parent->children(); foreach (ctkXnatObject *child, children) { if (url.indexOf(child->resourceUri()) != -1) { return child; } } return nullptr; } ctkXnatObject *QmitkXnatTreeModel::GetXnatObjectFromUrl(const QString &url) { QModelIndex index = this->index(0, 0, QModelIndex()); ctkXnatObject *currentXnatObject = nullptr; currentXnatObject = this->xnatObject(index); if (currentXnatObject != nullptr) { // 1. Find project ctkXnatObject *project = nullptr; project = this->InternalGetXnatObjectFromUrl("projects/", url, currentXnatObject); // 2. Find subject ctkXnatObject *subject = nullptr; if (project != nullptr) { currentXnatObject = project; subject = this->InternalGetXnatObjectFromUrl("subjects/", url, project); } // 3. Find experiment ctkXnatObject *experiment = nullptr; if (subject != nullptr) { currentXnatObject = subject; experiment = this->InternalGetXnatObjectFromUrl("experiments/", url, subject); } // 4. Find scan ctkXnatObject *scan = nullptr; if (experiment != nullptr) { currentXnatObject = experiment; scan = this->InternalGetXnatObjectFromUrl("scans/", url, experiment); } if (scan != nullptr) { scan->fetch(); QList scans = scan->children(); foreach (ctkXnatObject *child, scans) { if (url.indexOf(child->resourceUri()) != -1) { return child; } } } currentXnatObject->fetch(); QList bla = currentXnatObject->children(); foreach (ctkXnatObject *child, bla) { if (child->name() == "Resources") return child; } } return nullptr; } diff --git a/Plugins/org.blueberry.core.commands/src/berryExecutionEvent.cpp b/Plugins/org.blueberry.core.commands/src/berryExecutionEvent.cpp index 9df2db493f..d7da9f8f81 100644 --- a/Plugins/org.blueberry.core.commands/src/berryExecutionEvent.cpp +++ b/Plugins/org.blueberry.core.commands/src/berryExecutionEvent.cpp @@ -1,125 +1,125 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "berryExecutionEvent.h" #include "common/berryCommandExceptions.h" #include "berryIParameterValueConverter.h" #include "berryCommandCategory.h" #include "berryState.h" #include "berryIHandler.h" #include #include namespace berry { ExecutionEvent::ExecutionEvent() { } ExecutionEvent::ExecutionEvent(const Command::ConstPointer& cmd, const ParameterMap& params, const Object::ConstPointer& trg, const Object::Pointer& appContext) : applicationContext(appContext), command(cmd), parameters(params), trigger(trg) { } const Object::Pointer ExecutionEvent::GetApplicationContext() const { return applicationContext; } const Command::ConstPointer ExecutionEvent::GetCommand() const { return command; } const Object::ConstPointer ExecutionEvent::GetObjectParameterForExecution( const QString& parameterId) const { if (command.IsNull()) { throw ExecutionException( "No command is associated with this execution event"); //$NON-NLS-1$ } try { // const ParameterType parameterType = command // .getParameterType(parameterId); // if (parameterType == null) // { // throw new ExecutionException( // "Command does not have a parameter type for the given parameter"); //$NON-NLS-1$ // } // const AbstractParameterValueConverter valueConverter = parameterType // .getValueConverter(); // if (valueConverter == null) // { // throw new ExecutionException( // "Command does not have a value converter"); //$NON-NLS-1$ // } const QString stringValue = this->GetParameter(parameterId); ObjectString::Pointer objectValue(new ObjectString(stringValue)); // const Object objectValue = valueConverter // .convertToObject(stringValue); return objectValue; } - catch (NotDefinedException e) + catch (const NotDefinedException& e) { throw ExecutionException("Command is not defined", e); //$NON-NLS-1$ } -// catch (ParameterValueConversionException e) +// catch (const ParameterValueConversionException e) // { // throw new ExecutionException( // "The parameter string could not be converted to an object", e); //$NON-NLS-1$ // } } QString ExecutionEvent::GetParameter(const QString& parameterId) const { ParameterMap::const_iterator res = parameters.find(parameterId); if (res != parameters.end()) return res.value(); else return ""; } const ExecutionEvent::ParameterMap& ExecutionEvent::GetParameters() const { return parameters; } const Object::ConstPointer ExecutionEvent::GetTrigger() const { return trigger; } QString ExecutionEvent::ToString() const { QString str; QTextStream ss(&str); ss << "ExecutionEvent(" << command->ToString() << ',' << parameters.size() << ',' << (trigger ? trigger->ToString() : QString()) << ',' << applicationContext->ToString() << ')'; return str; } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryEditorManager.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryEditorManager.cpp index f595703bc6..a89d875734 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryEditorManager.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryEditorManager.cpp @@ -1,1295 +1,1295 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "berryEditorManager.h" #include "berryIWorkbenchPart.h" #include "berryIWorkbenchWindow.h" #include "berryIEditorRegistry.h" #include "berryUIException.h" #include "berryWorkbenchWindow.h" #include "berryWorkbenchPage.h" #include "berryEditorSite.h" #include "berryEditorReference.h" #include "berryWorkbenchPlugin.h" #include "berryWorkbenchConstants.h" #include "berryNullEditorInput.h" #include "berryEditorAreaHelper.h" #include "berryPartStack.h" #include namespace berry { const QString EditorManager::PIN_EDITOR_KEY = "PIN_EDITOR"; const QString EditorManager::RESOURCES_TO_SAVE_MESSAGE = "Select resources to save:"; const QString EditorManager::SAVE_RESOURCES_TITLE = "Save Resources"; EditorManager::EditorManager(WorkbenchWindow::Pointer wind, WorkbenchPage::Pointer workbenchPage, EditorAreaHelper* pres) : editorPresentation(pres), window(wind.GetPointer()), page(workbenchPage.GetPointer()) { poco_check_ptr(editorPresentation); poco_assert(window != nullptr); poco_assert(page != nullptr); //page.getExtensionTracker().registerHandler(this, null); } void EditorManager::CheckDeleteEditorResources() { // // get the current number of editors // IEditorReference[] editors = page.getEditorReferences(); // // If there are no editors // if (editors.length == 0) // { // if (editorPropChangeListnener != null) // { // // remove property change listener for editors // IPreferenceStore prefStore = WorkbenchPlugin.getDefault() // .getPreferenceStore(); // prefStore // .removePropertyChangeListener(editorPropChangeListnener); // editorPropChangeListnener = null; // } // if (pinEditorHandlerActivation != null) // { // // remove pin editor keyboard shortcut handler // final IHandlerService handlerService = (IHandlerService) window.getWorkbench().getService(IHandlerService.class); // handlerService.deactivateHandler(pinEditorHandlerActivation); // pinEditorHandlerActivation = null; // } // } } //void EditorManager::CheckCreateEditorPropListener() //{ // if (editorPropChangeListnener == null) // { // // Add a property change listener for closing editors automatically // // preference // // Add or remove the pin icon accordingly // editorPropChangeListnener = new IPropertyChangeListener() // { // public void propertyChange(PropertyChangeEvent event) // { // if (event.getProperty().equals( // IPreferenceConstants.REUSE_EDITORS_BOOLEAN)) // { // IEditorReference[] editors = getEditors(); // for (int i = 0; i < editors.length; i++) // { // ((EditorReference) editors[i]).pinStatusUpdated(); // } // } // } // }; // WorkbenchPlugin.getDefault().getPreferenceStore() // .addPropertyChangeListener(editorPropChangeListnener); // } //} //void EditorManager::CheckCreatePinEditorShortcutKeyHandler() //{ // if (pinEditorHandlerActivation == null) // { // final Shell shell = window.getShell(); // final IHandler pinEditorHandler = new AbstractHandler() // { // public final Object execute(final ExecutionEvent event) // { // // check if the "Close editors automatically" preference is // // set // IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore(); // if (store // .getBoolean(IPreferenceConstants.REUSE_EDITORS_BOOLEAN) // || ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).alwaysShowPinAction()) // { // // IWorkbenchPartReference ref = editorPresentation // .getVisibleEditor(); // if (ref instanceof WorkbenchPartReference) // { // WorkbenchPartReference concreteRef = (WorkbenchPartReference) ref; // // concreteRef.setPinned(concreteRef.isPinned()); // } // } // return null; // } // }; // // // Assign the handler for the pin editor keyboard shortcut. // final IHandlerService handlerService = (IHandlerService) window.getWorkbench().getService(IHandlerService.class); // pinEditorHandlerActivation = handlerService.activateHandler( // "org.blueberry.ui.window.pinEditor", pinEditorHandler, //$NON-NLS-1$ // new ActiveShellExpression(shell)); // } //} QList EditorManager::CollectDirtyEditors() { QList result; QList editors(page->GetEditorReferences()); for (QList::iterator i = editors.begin(); i != editors.end(); ++i) { IEditorPart::Pointer part = (*i)->GetPart(false).Cast(); if (part.IsNotNull() && part->IsDirty()) { result.push_back(part); } } return result; } bool EditorManager::ContainsEditor(IEditorReference::Pointer ref) { QList editors(page->GetEditorReferences()); return std::find(editors.begin(), editors.end(), ref) != editors.end(); } //EditorActionBars* EditorManager::CreateEditorActionBars( // EditorDescriptor::Pointer desc, IEditorSite::Pointer site) //{ // // Get the editor type. // String type = desc.getId(); // // // If an action bar already exists for this editor type return it. // EditorActionBars actionBars = (EditorActionBars) actionCache.get(type); // if (actionBars != null) // { // actionBars.addRef(); // return actionBars; // } // // // Create a new action bar set. // actionBars = new EditorActionBars(page, site.getWorkbenchWindow(), type); // actionBars.addRef(); // actionCache.put(type, actionBars); // // // Read base contributor. // IEditorActionBarContributor contr = desc.createActionBarContributor(); // if (contr != null) // { // actionBars.setEditorContributor(contr); // contr.init(actionBars, page); // } // // // Read action extensions. // EditorActionBuilder builder = new EditorActionBuilder(); // contr = builder.readActionExtensions(desc); // if (contr != null) // { // actionBars.setExtensionContributor(contr); // contr.init(actionBars, page); // } // // // Return action bars. // return actionBars; //} //EditorActionBars* EditorManager::CreateEmptyEditorActionBars( // IEditorSite::Pointer site) //{ // // Get the editor type. // String type = String.valueOf(System.currentTimeMillis()); // // // Create a new action bar set. // // Note: It is an empty set. // EditorActionBars actionBars = new EditorActionBars(page, site.getWorkbenchWindow(), type); // actionBars.addRef(); // actionCache.put(type, actionBars); // // // Return action bars. // return actionBars; //} //void EditorManager::DisposeEditorActionBars(EditorActionBars* actionBars) //{ // actionBars.removeRef(); // if (actionBars.getRef() <= 0) // { // String type = actionBars.getEditorType(); // actionCache.remove(type); // // refresh the cool bar manager before disposing of a cool item // ICoolBarManager2 coolBar = (ICoolBarManager2) window.getCoolBarManager2(); // if (coolBar != null) // { // coolBar.refresh(); // } // actionBars.dispose(); // } //} IEditorPart::Pointer EditorManager::FindEditor(IEditorInput::Pointer input) { return this->FindEditor("", input, IWorkbenchPage::MATCH_INPUT); } IEditorPart::Pointer EditorManager::FindEditor(const QString& editorId, IEditorInput::Pointer input, int matchFlags) { QList refs(this->FindEditors(input, editorId, matchFlags)); if (refs.size() == 0) { return IEditorPart::Pointer(); } return refs[0]->GetEditor(true); } QList EditorManager::FindEditors( IEditorInput::Pointer input, const QString& editorId, int matchFlags) { if (matchFlags == IWorkbenchPage::MATCH_NONE) { return QList(); } QList result; QList othersList(page->GetEditorReferences()); if (!othersList.empty()) { IEditorReference::Pointer active = page->GetActiveEditorReference(); if (active.IsNotNull()) { othersList.removeAll(active); QList activeList; activeList.push_back(active); this->FindEditors(activeList, input, editorId, matchFlags, result); } this->FindEditors(othersList, input, editorId, matchFlags, result); } return result; } void EditorManager::FindEditors( QList& editorList, IEditorInput::Pointer input, const QString& editorId, int matchFlags, QList& result) { if (matchFlags == IWorkbenchPage::MATCH_NONE) { return; } // Phase 0: Remove editors whose ids don't match (if matching by id) if (((matchFlags & IWorkbenchPage::MATCH_ID) != 0) && !editorId.isEmpty()) { for (QList::iterator i = editorList.begin(); i != editorList.end();) { if (editorId != (*i)->GetId()) { i = editorList.erase(i); continue; } ++i; } } // If not matching on editor input, just return the remaining editors. // In practice, this case is never used. if ((matchFlags & IWorkbenchPage::MATCH_INPUT) == 0) { result.append(editorList); return; } // Phase 1: check editors that have their own matching strategy for (QList::iterator i = editorList.begin(); i != editorList.end();) { EditorReference::Pointer editor = i->Cast(); IEditorDescriptor::Pointer desc = editor->GetDescriptor(); if (desc.IsNotNull()) { IEditorMatchingStrategy::Pointer matchingStrategy = desc ->GetEditorMatchingStrategy(); if (matchingStrategy.IsNotNull()) { i = editorList.erase(i); // We're handling this one here, so remove it // from the list. if (matchingStrategy->Matches(editor, input)) { result.push_back(editor); } continue; } } ++i; } // Phase 2: check materialized editors (without their own matching // strategy) for (QList::iterator i = editorList.begin(); i != editorList.end();) { EditorReference::Pointer editor = i->Cast(); IEditorPart::Pointer part = editor->GetPart(false).Cast(); if (part.IsNotNull()) { i = editorList.erase(i); // We're handling this one here, so remove it from // the list. if (part->GetEditorInput().IsNotNull() && part->GetEditorInput() == input) { result.push_back(editor); } } else ++i; } // Phase 3: check unmaterialized editors for input equality, // delaying plug-in activation further by only restoring the editor // input // if the editor reference's factory id and name match. // QString name = input->GetName(); // IPersistableElement persistable = input.getPersistable(); // if (name == null || persistable == null) // { // return; // } // String id = persistable.getFactoryId(); // if (id == null) // { // return; // } // for (Iterator i = editorList.iterator(); i.hasNext();) // { // EditorReference editor = (EditorReference) i.next(); // if (name.equals(editor.getName()) && id.equals(editor.getFactoryId())) // { // IEditorInput restoredInput; // try // { // restoredInput = editor.getEditorInput(); // if (Util.equals(restoredInput, input)) // { // result.add(editor); // } // } // catch (PartInitException e1) // { // WorkbenchPlugin.log(e1); // } // } // } } std::size_t EditorManager::GetEditorCount() { return page->GetEditorReferences().size(); } IEditorRegistry* EditorManager::GetEditorRegistry() { return WorkbenchPlugin::GetDefault()->GetEditorRegistry(); } QList EditorManager::GetDirtyEditors() { return this->CollectDirtyEditors(); } QList EditorManager::GetEditors() { return page->GetEditorReferences(); } IEditorPart::Pointer EditorManager::GetVisibleEditor() { IEditorReference::Pointer ref = editorPresentation->GetVisibleEditor(); if (ref.IsNull()) { return IEditorPart::Pointer(nullptr); } return ref->GetPart(true).Cast(); } bool EditorManager::IsSaveAllNeeded() { QList editors(page->GetEditorReferences()); for (QList::iterator i = editors.begin(); i != editors.end(); ++i) { if ((*i)->IsDirty()) { return true; } } return false; } IEditorReference::Pointer EditorManager::FindReusableEditor( EditorDescriptor::Pointer /*desc*/) { //return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).findReusableEditor(page); return IEditorReference::Pointer(nullptr); } IEditorReference::Pointer EditorManager::OpenEditor( const QString& editorId, IEditorInput::Pointer input, bool /*setVisible*/, IMemento::Pointer editorState) { if (input.IsNull()) { throw Poco::InvalidArgumentException(); } IEditorRegistry* reg = this->GetEditorRegistry(); EditorDescriptor::Pointer desc = reg->FindEditor(editorId).Cast(); if (desc.IsNull()) { throw PartInitException("Unable to open editor, unknown editor id: " + editorId); } return this->OpenEditorFromDescriptor(desc, input, editorState); } IEditorReference::Pointer EditorManager::OpenEditorFromDescriptor( EditorDescriptor::Pointer desc, IEditorInput::Pointer input, IMemento::Pointer editorState) { IEditorReference::Pointer result; if (desc->IsInternal()) { result = this->ReuseInternalEditor(desc, input); if (result.IsNull()) { result = new EditorReference(this, input, desc, editorState); } } // else if (desc->GetId() == IEditorRegistry::SYSTEM_INPLACE_EDITOR_ID) // { // if (ComponentSupport.inPlaceEditorSupported()) // { // result = new EditorReference(this, input, desc); // } // } // else if (desc->GetId() == IEditorRegistry::SYSTEM_EXTERNAL_EDITOR_ID) // { // IPathEditorInput pathInput = getPathEditorInput(input); // if (pathInput != null) // { // result = openSystemExternalEditor(pathInput.getPath()); // } // else // { // throw new PartInitException( // WorkbenchMessages.EditorManager_systemEditorError); // } // } // else if (desc->IsOpenExternal()) // { // result = openExternalEditor(desc, input); // } else { // this should never happen throw PartInitException("Invalid editor descriptor for id:" + desc->GetId()); } if (result.IsNotNull()) { this->CreateEditorTab(result.Cast(), ""); //$NON-NLS-1$ } // Workbench wb = (Workbench) window.getWorkbench(); // wb.getEditorHistory().add(input, desc); return result; } //IEditorReference::Pointer EditorManager::OpenExternalEditor( // EditorDescriptor::Pointer desc, IEditorInput::Pointer input) //{ // final CoreException ex[] = new CoreException[1]; // // final IPathEditorInput pathInput = getPathEditorInput(input); // if (pathInput != null && pathInput.getPath() != null) // { // BusyIndicator.showWhile(getDisplay(), new Runnable() // { // public void run() // { // try // { // if (desc.getLauncher() != null) // { // // open using launcher // Object launcher = WorkbenchPlugin.createExtension( // desc.getConfigurationElement(), "launcher"); //$NON-NLS-1$ // ((IEditorLauncher) launcher).open(pathInput // .getPath()); // } // else // { // // open using command // ExternalEditor oEditor = new ExternalEditor( // pathInput.getPath(), desc); // oEditor.open(); // } // } // catch (CoreException e) // { // ex[0] = e; // } // } // } // ); // } // else // { // throw new PartInitException(NLS.bind( // WorkbenchMessages.EditorManager_errorOpeningExternalEditor, // desc.getFileName(), desc.getId())); // } // // if (ex[0] != null) // { // throw new PartInitException(NLS.bind( // WorkbenchMessages.EditorManager_errorOpeningExternalEditor, // desc.getFileName(), desc.getId()), ex[0]); // } // // // we do not have an editor part for external editors // return null; //} void EditorManager::CreateEditorTab(EditorReference::Pointer ref, const QString& workbookId) { editorPresentation->AddEditor(ref, workbookId); } EditorSite::Pointer EditorManager::CreateSite(IEditorReference::Pointer ref, IEditorPart::Pointer part, EditorDescriptor::Pointer desc, IEditorInput::Pointer input) const { EditorSite::Pointer site(new EditorSite(ref, part, page, desc)); if (desc.IsNotNull()) { //site.setActionBars(createEditorActionBars(desc, site)); } else { //site.setActionBars(createEmptyEditorActionBars(site)); } const QString label = part->GetPartName(); // debugging only try { part->Init(site, input); // Sanity-check the site if (!(part->GetSite() == site) || !(part->GetEditorSite() == site)) { throw PartInitException("Editor initialization failed: " + desc->GetId() + ". Site is incorrect."); } } - catch (PartInitException e) + catch (const PartInitException &e) { throw e; } - catch (std::exception e) + catch (const std::exception &e) { throw PartInitException(QString("An exception was thrown during initialization: ") + e.what()); } return site; } IEditorReference::Pointer EditorManager::ReuseInternalEditor( EditorDescriptor::Pointer /*desc*/, IEditorInput::Pointer /*input*/) { // poco_assert(desc.IsNotNull()); // "descriptor must not be null"); //$NON-NLS-1$ // poco_assert(input.IsNotNull()); // "input must not be null"); //$NON-NLS-1$ // // IEditorReference::Pointer reusableEditorRef = this->FindReusableEditor(desc); // if (reusableEditorRef.IsNotNull()) // { // return this->ReuseInternalEditor(page, this, editorPresentation, desc, input, // reusableEditorRef); // } return IEditorReference::Pointer(nullptr); } IEditorPart::Pointer EditorManager::CreatePart(EditorDescriptor::Pointer desc) const { // try // { IEditorPart::Pointer result = desc->CreateEditor(); // IConfigurationElement element = desc.getConfigurationElement(); // if (element != null) // { // page.getExtensionTracker().registerObject( // element.getDeclaringExtension(), result, // IExtensionTracker.REF_WEAK); // } return result; // } // catch (CoreException e) // { // throw PartInitException(StatusUtil.newStatus( // desc.getPluginID(), // WorkbenchMessages.EditorManager_instantiationError, e)); // } } //IEditorReference::Pointer EditorManager::OpenSystemExternalEditor( // Poco::Path location) //{ // if (location == null) // { // throw new IllegalArgumentException(); // } // // final boolean result[] = // { false}; // BusyIndicator.showWhile(getDisplay(), new Runnable() // { // public void run() // { // if (location != null) // { // result[0] = Program.launch(location.toOSString()); // } // } // } // ); // // if (!result[0]) // { // throw new PartInitException(NLS.bind( // WorkbenchMessages.EditorManager_unableToOpenExternalEditor, // location)); // } // // // We do not have an editor part for external editors // return null; // } // ImageDescriptor EditorManager::FindImage(EditorDescriptor::Pointer desc, // Poco::Path path) // { // if (desc == null) // { // // @issue what should be the default image? // return ImageDescriptor.getMissingImageDescriptor(); // } // // if (desc.isOpenExternal() && path != null) // { // return PlatformUI.getWorkbench().getEditorRegistry() // .getImageDescriptor(path.toOSString()); // } // // return desc.getImageDescriptor(); // } bool EditorManager::RestoreState(IMemento::Pointer memento) { // Restore the editor area workbooks layout/relationship // MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, // IStatus.OK, // WorkbenchMessages.EditorManager_problemsRestoringEditors, null); bool result = true; QString activeWorkbookID; QList visibleEditors; QList activeEditor; IMemento::Pointer areaMem = memento->GetChild(WorkbenchConstants::TAG_AREA); if (areaMem) { //result.add(editorPresentation.restoreState(areaMem)); editorPresentation->RestoreState(areaMem); areaMem->GetString(WorkbenchConstants::TAG_ACTIVE_WORKBOOK, activeWorkbookID); } // Loop through the editors. QList editorMems(memento->GetChildren(WorkbenchConstants::TAG_EDITOR)); for (int x = 0; x < editorMems.size(); x++) { // for dynamic UI - call restoreEditorState to replace code which is // commented out RestoreEditorState(editorMems[x], visibleEditors, activeEditor); //, result); } // restore the presentation if (areaMem) { //result.add(editorPresentation.restorePresentationState(areaMem)); result &= editorPresentation->RestorePresentationState(areaMem); } try { // StartupThreading.runWithThrowable(new StartupRunnable() // { // // public void runWithException() throws Throwable // { // Update each workbook with its visible editor. for (int i = 0; i < visibleEditors.size(); i++) { SetVisibleEditor(visibleEditors[i], false); } // Update the active workbook if (!activeWorkbookID.isEmpty()) { editorPresentation->SetActiveEditorWorkbookFromID(activeWorkbookID); } if (!activeEditor.empty() && activeEditor[0]) { IWorkbenchPart::Pointer editor = activeEditor[0]->GetPart(true); if (editor) { page->Activate(editor); } } // }}); } catch (...) { // The exception is already logged. // result // .add(new Status( // IStatus.ERR, // PlatformUI.PLUGIN_ID, // 0, // WorkbenchMessages.EditorManager_exceptionRestoringEditor, // t)); result &= false; } return result; } bool EditorManager::SaveAll(bool confirm, bool closing, bool addNonPartSources) { // Get the list of dirty editors and views. If it is // empty just return. QList parts(page->GetDirtyParts()); if (parts.empty()) { return true; } QList wbParts; for (QList::const_iterator i = parts.begin(); i != parts.end(); ++i) { if (IWorkbenchPart::Pointer part = i->Cast()) { wbParts.push_back(part); } } // If confirmation is required .. return this->SaveAll(wbParts, confirm, closing, addNonPartSources, IWorkbenchWindow::Pointer(window)); } bool EditorManager::SaveAll( const QList& /*dirtyParts*/, bool /*confirm*/, bool /*closing*/, bool /*addNonPartSources*/, SmartPointer /*window*/) { // // clone the input list // dirtyParts = new ArrayList(dirtyParts); // List modelsToSave; // if (confirm) { // boolean saveable2Processed = false; // // Process all parts that implement ISaveablePart2. // // These parts are removed from the list after saving // // them. We then need to restore the workbench to // // its previous state, for now this is just last // // active perspective. // // Note that the given parts may come from multiple // // windows, pages and perspectives. // ListIterator listIterator = dirtyParts.listIterator(); // // WorkbenchPage currentPage = null; // Perspective currentPageOriginalPerspective = null; // while (listIterator.hasNext()) { // IWorkbenchPart part = (IWorkbenchPart) listIterator.next(); // if (part instanceof ISaveablePart2) { // WorkbenchPage page = (WorkbenchPage) part.getSite() // .getPage(); // if (!Util.equals(currentPage, page)) { // if (currentPage != null // && currentPageOriginalPerspective != null) { // if (!currentPageOriginalPerspective // .equals(currentPage.getActivePerspective())) { // currentPage // .setPerspective(currentPageOriginalPerspective // .getDesc()); // } // } // currentPage = page; // currentPageOriginalPerspective = page // .getActivePerspective(); // } // if (confirm) { // if (part instanceof IViewPart) { // Perspective perspective = page // .getFirstPerspectiveWithView((IViewPart) part); // if (perspective != null) { // page.setPerspective(perspective.getDesc()); // } // } // // show the window containing the page? // IWorkbenchWindow partsWindow = page // .getWorkbenchWindow(); // if (partsWindow != partsWindow.getWorkbench() // .getActiveWorkbenchWindow()) { // Shell shell = partsWindow.getShell(); // if (shell.getMinimized()) { // shell.setMinimized(false); // } // shell.setActive(); // } // page.bringToTop(part); // } // // try to save the part // int choice = SaveableHelper.savePart((ISaveablePart2) part, // page.getWorkbenchWindow(), confirm); // if (choice == ISaveablePart2.CANCEL) { // // If the user cancels, don't restore the previous // // workbench state, as that will // // be an unexpected switch from the current state. // return false; // } else if (choice != ISaveablePart2.DEFAULT) { // saveable2Processed = true; // listIterator.remove(); // } // } // } // // // try to restore the workbench to its previous state // if (currentPage != null && currentPageOriginalPerspective != null) { // if (!currentPageOriginalPerspective.equals(currentPage // .getActivePerspective())) { // currentPage.setPerspective(currentPageOriginalPerspective // .getDesc()); // } // } // // // if processing a ISaveablePart2 caused other parts to be // // saved, remove them from the list presented to the user. // if (saveable2Processed) { // listIterator = dirtyParts.listIterator(); // while (listIterator.hasNext()) { // ISaveablePart part = (ISaveablePart) listIterator.next(); // if (!part.isDirty()) { // listIterator.remove(); // } // } // } // // modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); // // // If nothing to save, return. // if (modelsToSave.isEmpty()) { // return true; // } // boolean canceled = SaveableHelper.waitForBackgroundSaveJobs(modelsToSave); // if (canceled) { // return false; // } // // Use a simpler dialog if there's only one // if (modelsToSave.size() == 1) { // Saveable model = (Saveable) modelsToSave.get(0); // String message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, model.getName()); // // Show a dialog. // String[] buttons = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }; // MessageDialog d = new MessageDialog( // shellProvider.getShell(), WorkbenchMessages.Save_Resource, // null, message, MessageDialog.QUESTION, buttons, 0); // // int choice = SaveableHelper.testGetAutomatedResponse(); // if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) { // choice = d.open(); // } // // // Branch on the user choice. // // The choice id is based on the order of button labels // // above. // switch (choice) { // case ISaveablePart2.YES: // yes // break; // case ISaveablePart2.NO: // no // return true; // default: // case ISaveablePart2.CANCEL: // cancel // return false; // } // } // else { // ListSelectionDialog dlg = new ListSelectionDialog( // shellProvider.getShell(), modelsToSave, // new ArrayContentProvider(), // new WorkbenchPartLabelProvider(), RESOURCES_TO_SAVE_MESSAGE); // dlg.setInitialSelections(modelsToSave.toArray()); // dlg.setTitle(SAVE_RESOURCES_TITLE); // // // this "if" statement aids in testing. // if (SaveableHelper.testGetAutomatedResponse()==SaveableHelper.USER_RESPONSE) { // int result = dlg.open(); // //Just return false to prevent the operation continuing // if (result == IDialogConstants.CANCEL_ID) { // return false; // } // // modelsToSave = Arrays.asList(dlg.getResult()); // } // } // } // else { // modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); // } // // // If the editor list is empty return. // if (modelsToSave.isEmpty()) { // return true; // } // // // Create save block. // final List finalModels = modelsToSave; // IRunnableWithProgress progressOp = new IRunnableWithProgress() { // public void run(IProgressMonitor monitor) { // IProgressMonitor monitorWrap = new EventLoopProgressMonitor( // monitor); // monitorWrap.beginTask("", finalModels.size()); //$NON-NLS-1$ // for (Iterator i = finalModels.iterator(); i.hasNext();) { // Saveable model = (Saveable) i.next(); // // handle case where this model got saved as a result of saving another // if (!model.isDirty()) { // monitor.worked(1); // continue; // } // SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), shellProvider, closing || confirm); // if (monitorWrap.isCanceled()) { // break; // } // } // monitorWrap.done(); // } // }; // // // Do the save. // return SaveableHelper.runProgressMonitorOperation( // WorkbenchMessages.Save_All, progressOp, runnableContext, shellProvider); return true; } bool EditorManager::SavePart(ISaveablePart::Pointer /*saveable*/, IWorkbenchPart::Pointer /*part*/, bool /*confirm*/) { //TODO EditorManager save part (SaveableHelper) //return SaveableHelper.savePart(saveable, part, window, confirm); return true; } bool EditorManager::SaveState(const IMemento::Pointer memento) { // final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, // IStatus.OK, // WorkbenchMessages.EditorManager_problemsSavingEditors, null); bool result = true; // Save the editor area workbooks layout/relationship IMemento::Pointer editorAreaMem = memento->CreateChild(WorkbenchConstants::TAG_AREA); //result.add(editorPresentation.saveState(editorAreaMem)); result &= editorPresentation->SaveState(editorAreaMem); // Save the active workbook id editorAreaMem->PutString(WorkbenchConstants::TAG_ACTIVE_WORKBOOK, editorPresentation->GetActiveEditorWorkbookID()); // Get each workbook QList workbooks(editorPresentation->GetWorkbooks()); for (QList::iterator iter = workbooks.begin(); iter != workbooks.end(); ++iter) { PartStack::Pointer workbook = *iter; // Use the list of editors found in EditorStack; fix for 24091 QList editorPanes(workbook->GetChildren()); for (QList::iterator i = editorPanes.begin(); i != editorPanes.end(); ++i) { // Save each open editor. EditorReference::Pointer editorReference = i->Cast()->GetPartReference().Cast(); IEditorPart::Pointer editor = editorReference->GetEditor(false); if (!editor) { if (editorReference->GetMemento()) { IMemento::Pointer editorMem = memento ->CreateChild(WorkbenchConstants::TAG_EDITOR); editorMem->PutMemento(editorReference->GetMemento()); } continue; } // for dynamic UI - add the next line to replace the subsequent // code which is commented out SaveEditorState(memento, editorReference); //, result); } } return result; } bool EditorManager::SetVisibleEditor(IEditorReference::Pointer newEd, bool setFocus) { return editorPresentation->SetVisibleEditor(newEd, setFocus); } IPathEditorInput::Pointer EditorManager::GetPathEditorInput( IEditorInput::Pointer input) { if (input.Cast().IsNotNull()) { return input.Cast(); } // return (IPathEditorInput) // Util.getAdapter(input, IPathEditorInput.class); return IPathEditorInput::Pointer(nullptr); } void EditorManager::RestoreEditorState(IMemento::Pointer /*editorMem*/, QList& /*visibleEditors*/, QList& /*activeEditor*/) { // MultiStatus result) { //TODO Restore editor state // String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS); // boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$ // EditorReference::Pointer e = new EditorReference(this, editorMem); // // try // { // StartupThreading.runWithPartInitExceptions(new StartupRunnable () // { // // public void runWithException() throws Throwable // { // createEditorTab(e, workbookID); // }}); // // } // catch (PartInitException ex) // { // result.add(ex.getStatus()); // } // // String strActivePart = editorMem // .getString(IWorkbenchConstants.TAG_ACTIVE_PART); // if ("true".equals(strActivePart)) // { //$NON-NLS-1$ // activeEditor[0] = e; // } // // String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS); // boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$ // if (visibleEditor) // { // visibleEditors.add(e); // } } void EditorManager::SaveEditorState(IMemento::Pointer /*mem*/, IEditorReference::Pointer /*ed*/) { //TODO Save editor state // final EditorReference editorRef = (EditorReference) ed; // final IEditorPart editor = ed.getEditor(false); // final IMemento memento = mem; // final MultiStatus result = res; // if (!(editor.getEditorSite() instanceof EditorSite)) // { // return; // } // final EditorSite site = (EditorSite) editor.getEditorSite(); // if (site.getPane() instanceof MultiEditorInnerPane) // { // return; // } // // SafeRunner.run(new SafeRunnable() // { // public void run() // { // // Get the input. // IEditorInput input = editor.getEditorInput(); // if (!input.exists()) // { // return; // } // IPersistableElement persistable = input.getPersistable(); // if (persistable == null) // { // return; // } // // // Save editor. // IMemento editorMem = memento // .createChild(IWorkbenchConstants.TAG_EDITOR); // editorMem.putString(IWorkbenchConstants.TAG_TITLE, editorRef // .getTitle()); // editorMem.putString(IWorkbenchConstants.TAG_NAME, editorRef // .getName()); // editorMem.putString(IWorkbenchConstants.TAG_ID, editorRef // .getId()); // editorMem.putString(IWorkbenchConstants.TAG_TOOLTIP, editorRef // .getTitleToolTip()); // // editorMem.putString(IWorkbenchConstants.TAG_PART_NAME, // editorRef.getPartName()); // // if (editor instanceof IWorkbenchPart3) // { // Map properties = ((IWorkbenchPart3) editor) // .getPartProperties(); // if (!properties.isEmpty()) // { // IMemento propBag = editorMem // .createChild(IWorkbenchConstants.TAG_PROPERTIES); // Iterator i = properties.entrySet().iterator(); // while (i.hasNext()) // { // Map.Entry entry = (Map.Entry) i.next(); // IMemento p = propBag.createChild( // IWorkbenchConstants.TAG_PROPERTY, // (String) entry.getKey()); // p.putTextData((String) entry.getValue()); // } // } // } // // if (editorRef.isPinned()) // { // editorMem.putString(IWorkbenchConstants.TAG_PINNED, "true"); //$NON-NLS-1$ // } // // EditorPane editorPane = (EditorPane) ((EditorSite) editor // .getEditorSite()).getPane(); // editorMem.putString(IWorkbenchConstants.TAG_WORKBOOK, // editorPane.getWorkbook().getID()); // // if (editor == page.getActivePart()) // { // editorMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART, // "true"); //$NON-NLS-1$ // } // // if (editorPane == editorPane.getWorkbook().getSelection()) // { // editorMem.putString(IWorkbenchConstants.TAG_FOCUS, "true"); //$NON-NLS-1$ // } // // if (input instanceof IPathEditorInput) // { // IPath path = ((IPathEditorInput) input).getPath(); // if (path != null) // { // editorMem.putString(IWorkbenchConstants.TAG_PATH, path // .toString()); // } // } // // // Save input. // IMemento inputMem = editorMem // .createChild(IWorkbenchConstants.TAG_INPUT); // inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, // persistable.getFactoryId()); // persistable.saveState(inputMem); // // // any editors that want to persist state // if (editor instanceof IPersistableEditor) // { // IMemento editorState = editorMem // .createChild(IWorkbenchConstants.TAG_EDITOR_STATE); // ((IPersistableEditor) editor).saveState(editorState); // } // } // // public void handleException(Throwable e) // { // result // .add(new Status( // IStatus.ERR, // PlatformUI.PLUGIN_ID, // 0, // NLS // .bind( // WorkbenchMessages.EditorManager_unableToSaveEditor, // editorRef.getTitle()), e)); // } // } // ); } IMemento::Pointer EditorManager::GetMemento(IEditorReference::Pointer e) { if (e.Cast().IsNotNull()) { return e.Cast()->GetMemento(); } return IMemento::Pointer(nullptr); } IEditorReference::Pointer EditorManager::OpenEmptyTab() { IEditorInput::Pointer input(new NullEditorInput()); EditorDescriptor::Pointer desc = (dynamic_cast(this->GetEditorRegistry())) ->FindEditor(EditorRegistry::EMPTY_EDITOR_ID).Cast(); EditorReference::Pointer result(new EditorReference(this, input, desc)); try { this->CreateEditorTab(result, ""); return result; } catch (const PartInitException& e) { // StatusManager.getManager().handle( // StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH, e)); BERRY_ERROR << e.what() << std::endl; } return IEditorReference::Pointer(nullptr); } bool EditorManager::UseIPersistableEditor() { // IPreferenceStore store = WorkbenchPlugin.getDefault() // .getPreferenceStore(); // return store.getBoolean(IPreferenceConstants.USE_IPERSISTABLE_EDITORS); return false; } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryEditorReference.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryEditorReference.cpp index 2a6a4069e8..20edf1abf4 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryEditorReference.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryEditorReference.cpp @@ -1,572 +1,572 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "tweaklets/berryWorkbenchPageTweaklet.h" #include "berryEditorReference.h" #include "berryEditorManager.h" #include "berryEditorDescriptor.h" #include "berryEditorRegistry.h" #include "berryEditorSite.h" #include "berryEditorAreaHelper.h" #include "berryWorkbenchPlugin.h" #include "berryWorkbenchPage.h" #include "berryNullEditorInput.h" #include "berryPartTester.h" #include "berryPlatformUI.h" #include "berryIWorkbenchPartConstants.h" namespace berry { EditorReference::EditorReference(EditorManager* man, IEditorInput::Pointer input, EditorDescriptor::Pointer desc, IMemento::Pointer editorState) : manager(man), expectingInputChange(false), reportedMalfunctioningEditor(false) { this->InitListenersAndHandlers(); restoredInput = input; this->editorState = editorState; this->Init(desc->GetId(), "", desc->GetImageDescriptor(), desc->GetLabel(), ""); } EditorReference::EditorReference(EditorManager* man, IMemento::Pointer memento) : manager(man), expectingInputChange(false), reportedMalfunctioningEditor(false) { this->InitListenersAndHandlers(); this->editorMemento = memento; if (manager->UseIPersistableEditor()) { //editorState = editorMemento->GetChild(WorkbenchConstants::TAG_EDITOR_STATE); } else { editorState = nullptr; } // String id = memento.getString(IWorkbenchConstants.TAG_ID); // String title = memento.getString(IWorkbenchConstants.TAG_TITLE); // String tooltip = Util.safeString(memento // .getString(IWorkbenchConstants.TAG_TOOLTIP)); // String partName = memento // .getString(IWorkbenchConstants.TAG_PART_NAME); // // IMemento propBag = memento.getChild(IWorkbenchConstants.TAG_PROPERTIES); // if (propBag != null) // { // IMemento[] props = propBag // .getChildren(IWorkbenchConstants.TAG_PROPERTY); // for (int i = 0; i < props.length; i++) // { // propertyCache.put(props[i].getID(), props[i].getTextData()); // } // } // For compatibility set the part name to the title if not found // if (partName.empty()) // { // partName = title; // } // Get the editor descriptor. // EditorDescriptor::Pointer desc; // if (id != null) // { // desc = getDescriptor(id); // } // // desc may be null if id is null or desc is not found, but findImage below handles this // String location = memento.getString(IWorkbenchConstants.TAG_PATH); // IPath path = location == null ? null : new Path(location); // ImageDescriptor iDesc = this.manager.findImage(desc, path); // // this.name = memento.getString(IWorkbenchConstants.TAG_NAME); // if (this.name == null) // { // this.name = title; // } // setPinned("true".equals(memento.getString(IWorkbenchConstants.TAG_PINNED))); //$NON-NLS-1$ // // IMemento inputMem = memento.getChild(IWorkbenchConstants.TAG_INPUT); // if (inputMem != null) // { // this.factoryId = inputMem // .getString(IWorkbenchConstants.TAG_FACTORY_ID); // } // // init(id, title, tooltip, iDesc, partName, ""); //$NON-NLS-1$ } EditorDescriptor::Pointer EditorReference::GetDescriptor() { return this->GetDescriptor(this->GetId()); } EditorDescriptor::Pointer EditorReference::GetDescriptor(const QString& id) { EditorDescriptor::Pointer desc; IEditorRegistry* reg = WorkbenchPlugin::GetDefault()->GetEditorRegistry(); desc = reg->FindEditor(id).Cast (); return desc; } void EditorReference::InitListenersAndHandlers() { // Create a property change listener to track the "close editors automatically" // preference and show/remove the pin icon on editors // Only 1 listener will be created in the EditorManager when necessary //this->manager->CheckCreateEditorPropListener(); // Create a keyboard shortcut handler for pinning editors // Only 1 handler will be created in the EditorManager when necessary //this->manager->CheckCreatePinEditorShortcutKeyHandler(); } PartPane::Pointer EditorReference::CreatePane() { PartPane::Pointer pane( new PartPane(IWorkbenchPartReference::Pointer(this), this->manager->page)); return pane; //return Tweaklets::Get(WorkbenchTweaklet::KEY)->CreateEditorPane(this, // this->manager->page); } void EditorReference::PinStatusUpdated() { //firePropertyChange(IWorkbenchPart.PROP_TITLE); } QString EditorReference::GetFactoryId() { // IEditorPart editor = getEditor(false); // if (editor != null) // { // IPersistableElement persistable = editor.getEditorInput() // .getPersistable(); // if (persistable != null) // { // return persistable.getFactoryId(); // } // return null; // } // return factoryId; return ""; } QString EditorReference::ComputePartName() const { return WorkbenchPartReference::ComputePartName(); } QString EditorReference::GetName() { if (part.IsNotNull()) { return this->GetEditor(false)->GetEditorInput()->GetName(); } return name; } IEditorPart::Pointer EditorReference::GetEditor(bool restore) { return this->GetPart(restore).Cast (); } void EditorReference::SetName(const QString& name) { this->name = name; } IMemento::Pointer EditorReference::GetMemento() { return editorMemento; } IWorkbenchPage::Pointer EditorReference::GetPage() const { return IWorkbenchPage::Pointer(this->manager->page); } IEditorInput::Pointer EditorReference::GetEditorInput() { IEditorPart::Pointer part = this->GetEditor(false); if (part.IsNotNull()) { return part->GetEditorInput(); } return this->GetRestoredInput(); } IEditorInput::Pointer EditorReference::GetRestoredInput() { if (restoredInput.IsNotNull()) { return restoredInput; } // Get the input factory. // IMemento::Pointer editorMem = this->GetMemento(); // if (editorMem == null) // { // throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_no_persisted_state, getId(), getName())); // } // IMemento inputMem = editorMem // .getChild(IWorkbenchConstants.TAG_INPUT); // String factoryID = null; // if (inputMem != null) // { // factoryID = inputMem // .getString(IWorkbenchConstants.TAG_FACTORY_ID); // } // if (factoryID == null) // { // throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_no_input_factory_ID, getId(), getName())); // } // IAdaptable input = null; // String label = null; // debugging only // if (UIStats.isDebugging(UIStats.CREATE_PART_INPUT)) // { // label = getName() != null ? getName() : factoryID; // } // try // { // UIStats.start(UIStats.CREATE_PART_INPUT, label); // IElementFactory factory = PlatformUI.getWorkbench() // .getElementFactory(factoryID); // if (factory == null) // { // throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_bad_element_factory, new Object[] // { factoryID, getId(), getName()})); // } // // // Get the input element. // input = factory.createElement(inputMem); // if (input == null) // { // throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_create_element_returned_null, new Object[] // { factoryID, getId(), getName()})); // } // }finally // { // UIStats.end(UIStats.CREATE_PART_INPUT, input, label); // } // if (!(input instanceof IEditorInput)) // { // throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_wrong_createElement_result, new Object[] // { factoryID, getId(), getName()})); // } // restoredInput = (IEditorInput) input; return restoredInput; } IWorkbenchPart::Pointer EditorReference::CreatePart() { if (EditorRegistry::EMPTY_EDITOR_ID == this->GetId()) { return this->GetEmptyEditor(this->GetDescriptor()); } IWorkbenchPart::Pointer result; // Try to restore the editor -- this does the real work of restoring the editor // try { result = this->CreatePartHelper().Cast (); - } catch (PartInitException e) + } catch (const PartInitException &e) { // If unable to create the part, create an error part instead // and pass the error to the status handling facility // IStatus originalStatus = exception.getStatus(); // IStatus logStatus = StatusUtil.newStatus(originalStatus, // NLS.bind("Unable to create editor ID {0}: {1}", //$NON-NLS-1$ // getId(), originalStatus.getMessage())); // IStatus displayStatus = StatusUtil.newStatus(originalStatus, // NLS.bind(WorkbenchMessages.EditorManager_unableToCreateEditor, // originalStatus.getMessage())); WorkbenchPlugin::Log(QString("Unable to create editor ID ") + this->GetId() + ": " + e.what()); // Pass the error to the status handling facility //StatusManager.getManager().handle(logStatus); EditorDescriptor::Pointer descr = this->GetDescriptor(); QString label = this->GetId(); if (descr.IsNotNull()) label = descr->GetLabel(); IEditorPart::Pointer part = Tweaklets::Get(WorkbenchPageTweaklet::KEY)->CreateErrorEditorPart(label, e.what()); if (part.IsNotNull()) { IEditorInput::Pointer input; try { input = this->GetEditorInput(); - } catch (PartInitException e1) + } catch (PartInitException &e1) { input = new NullEditorInput(EditorReference::Pointer(this)); } PartPane::Pointer pane = this->GetPane(); pane->CreateControl( manager->page->GetEditorPresentation()->GetLayoutPart()->GetControl()); EditorSite::Pointer site( new EditorSite(IEditorReference::Pointer(this), part, manager->page, descr)); //site.setActionBars(new EditorActionBars(manager.page, site.getWorkbenchWindow(), getId())); part->Init(site, input); try { part->CreatePartControl(pane->GetControl()); } catch (...) { //content.dispose(); //StatusUtil.handleStatus(e, StatusManager.SHOW // | StatusManager.LOG); WorkbenchPlugin::Log("Error creating editor"); return IWorkbenchPart::Pointer(nullptr); } result = part.Cast (); } } return result; } void EditorReference::PropertyChanged(Object::Pointer source, int propId) { // Detect badly behaved editors that don't fire PROP_INPUT events // when they're supposed to. This branch is only needed to handle // malfunctioning editors. if (propId == IWorkbenchPartConstants::PROP_INPUT) { expectingInputChange = false; } WorkbenchPartReference::PropertyChanged(source, propId); } bool EditorReference::SetInput(IEditorInput::Pointer input) { if (part.IsNotNull()) { if (part.Cast ().IsNotNull()) { IReusableEditor::Pointer editor = part.Cast (); expectingInputChange = true; editor->SetInput(input); // If the editor never fired a PROP_INPUT event, log the fact that we've discovered // a buggy editor and fire the event for free. Firing the event for free isn't required // and cannot be relied on (it only works if the input change was triggered by this // method, and there are definitely other cases where events will still be lost), // but older versions of the workbench did this so we fire it here in the spirit // of playing nice. if (expectingInputChange) { // Log the fact that this editor is broken this->ReportMalfunction( "Editor is not firing a PROP_INPUT event in response to IReusableEditor.setInput(...)"); //$NON-NLS-1$ // Fire the property for free (can't be relied on since there are other ways the input // can change, but we do it here to be consistent with older versions of the workbench) FirePropertyChange(IWorkbenchPartConstants::PROP_INPUT); } return editor->GetEditorInput() == input; } // Can't change the input if the editor already exists and isn't an IReusableEditor return false; } // Changing the input is trivial and always succeeds if the editor doesn't exist yet if (input != restoredInput) { restoredInput = input; //firePropertyChange(IWorkbenchPartConstants.PROP_INPUT); } return true; } void EditorReference::ReportMalfunction(const QString& string) { if (!reportedMalfunctioningEditor) { reportedMalfunctioningEditor = true; QString errorMessage = "Problem detected with part " + this->GetId(); //$NON-NLS-1$ if (part.IsNotNull()) { errorMessage.append("(class = ").append(part->GetClassName()).append( ")"); //$NON-NLS-1$ //$NON-NLS-2$ } errorMessage += ": " + string; //$NON-NLS-1$ //StatusManager.getManager().handle(StatusUtil.newStatus(getDescriptor().getPluginId(), errorMessage, null)); BERRY_ERROR << errorMessage << std::endl; } } IEditorPart::Pointer EditorReference::CreatePartHelper() { EditorSite::Pointer site; IEditorPart::Pointer part; try { IEditorInput::Pointer editorInput = this->GetEditorInput(); // Get the editor descriptor. QString editorID = this->GetId(); EditorDescriptor::Pointer desc = this->GetDescriptor(); if (desc.IsNull()) { throw PartInitException("No editor descriptor for id " + editorID); } if (desc->IsInternal()) { // Create an editor instance. part = manager->CreatePart(desc); this->CreatePartProperties(part); } // else if (desc->GetId() == IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID) // { // // part = ComponentSupport.getSystemInPlaceEditor(); // // if (part == null) // { // throw new PartInitException(WorkbenchMessages.EditorManager_no_in_place_support); // } // } else { throw PartInitException("Invalid editor descriptor for id " + editorID); } // Create a pane for this part PartPane::Pointer pane = this->GetPane(); pane->CreateControl(manager->page->GetEditorPresentation()->GetLayoutPart()->GetControl()); // Link everything up to the part reference (the part reference itself should not have // been modified until this point) site = manager->CreateSite(IEditorReference::Pointer(this), part, desc, editorInput); // if there is saved state that's appropriate, pass it on if (/*part instanceof IPersistableEditor &&*/editorState.IsNotNull()) { //part->RestoreState(editorState); } // Remember the site and the action bars (now that we've created them, we'll need to dispose // them if an exception occurs) //actionBars = (EditorActionBars) site.getActionBars(); part->CreatePartControl(pane->GetControl()); // The editor should now be fully created. Exercise its public interface, and sanity-check // it wherever possible. If it's going to throw exceptions or behave badly, it's much better // that it does so now while we can still cancel creation of the part. PartTester::TestEditor(part); return part; - } catch (std::exception e) + } catch (const std::exception &e) { throw PartInitException(e.what()); } } IEditorPart::Pointer EditorReference::GetEmptyEditor( EditorDescriptor::Pointer descr) { IEditorPart::Pointer part = Tweaklets::Get(WorkbenchPageTweaklet::KEY)->CreateErrorEditorPart("(Empty)", ""); IEditorInput::Pointer input; try { input = this->GetEditorInput(); - } catch (PartInitException e1) + } catch (const PartInitException &e1) { input = new NullEditorInput(EditorReference::Pointer(this)); } PartPane::Pointer pane = this->GetPane(); pane->CreateControl( manager->page->GetEditorPresentation()->GetLayoutPart()->GetControl()); EditorSite::Pointer site(new EditorSite(IEditorReference::Pointer(this), part, manager->page, descr)); //site.setActionBars(new EditorActionBars(manager.page, site.getWorkbenchWindow(), getId())); part->Init(site, input); try { part->CreatePartControl(pane->GetControl()); - } catch (std::exception e) + } catch (const std::exception &e) { //StatusManager.getManager().handle( // StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH, e)); BERRY_ERROR << e.what() << std::endl; return IEditorPart::Pointer(nullptr); } this->part = part.Cast (); // Add a dispose listener to the part. This dispose listener does nothing but log an exception // if the part's widgets get disposed unexpectedly. The workbench part reference is the only // object that should dispose this control, and it will remove the listener before it does so. this->RefreshFromPart(); //this->ReleaseReferences(); if (this->GetPage().Cast ()->GetActiveEditorReference() != this) { //fireInternalPropertyChange(INTERNAL_PROPERTY_OPENED); } return part; } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistryReader.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistryReader.cpp index 39f44724bb..e2aabe5e09 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistryReader.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistryReader.cpp @@ -1,113 +1,113 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "berryViewRegistryReader.h" #include "berryViewRegistry.h" #include "berryWorkbenchRegistryConstants.h" #include "berryWorkbenchPlugin.h" #include "berryPlatformUI.h" namespace berry { QString ViewRegistryReader::GENERAL_VIEW_ID = "org.blueberry.ui"; ViewRegistryReader::ViewRegistryReader() : RegistryReader() { } void ViewRegistryReader::ReadViews(IExtensionRegistry* in, ViewRegistry* out) { // this does not seem to really ever be throwing an the exception viewRegistry = out; this->ReadRegistry(in, PlatformUI::PLUGIN_ID(), WorkbenchRegistryConstants::PL_VIEWS); } void ViewRegistryReader::ReadCategory(const IConfigurationElement::Pointer& element) { try { Category::Pointer cat(new Category(element)); viewRegistry->Add(cat); } - catch (CoreException e) + catch (const CoreException &e) { // log an error since its not safe to show a dialog here WorkbenchPlugin::Log( "Unable to create view category.", e); } } bool ViewRegistryReader::ReadElement(const SmartPointer &element) { QString elementName = element->GetName(); if (elementName == WorkbenchRegistryConstants::TAG_VIEW) { this->ReadView(element); return true; } if (elementName == WorkbenchRegistryConstants::TAG_CATEGORY) { this->ReadCategory(element); this->ReadElementChildren(element); return true; } if (elementName == WorkbenchRegistryConstants::TAG_STICKYVIEW) { this->ReadSticky(element); return true; } return false; } void ViewRegistryReader::ReadSticky(const SmartPointer &element) { try { viewRegistry->Add(StickyViewDescriptor::Pointer(new StickyViewDescriptor(element))); } - catch (CoreException& e) + catch (const CoreException& e) { //TODO IStatus // log an error since its not safe to open a dialog here // WorkbenchPlugin.log( // "Unable to create sticky view descriptor.", e.getStatus());//$NON-NLS-1$ WorkbenchPlugin::Log("Unable to create sticky view descriptor.", e); } } void ViewRegistryReader::ReadView(const SmartPointer &element) { try { ViewDescriptor::Pointer desc(new ViewDescriptor(element)); viewRegistry->Add(desc); } - catch (CoreException e) + catch (const CoreException &e) { // log an error since its not safe to open a dialog here WorkbenchPlugin::Log( "Unable to create view descriptor.", e);//$NON-NLS-1$ } } }