diff --git a/CMake/PackageDepends/MITK_Qt5_Config.cmake b/CMake/PackageDepends/MITK_Qt5_Config.cmake new file mode 100644 index 0000000000..d315a30d33 --- /dev/null +++ b/CMake/PackageDepends/MITK_Qt5_Config.cmake @@ -0,0 +1,19 @@ +macro(use_qt5_module module) + + find_package(Qt5${module} REQUIRED) + + list(APPEND ALL_INCLUDE_DIRECTORIES ${Qt5${module}_INCLUDE_DIRS}) + list(APPEND ALL_LIBRARIES ${Qt5${module}_LIBRARIES}) + +endmacro() + +use_qt5_module(Core) +use_qt5_module(Quick) +use_qt5_module(Qml) +use_qt5_module(Widgets) +use_qt5_module(OpenGL) + +# Qt demands this.. (at least in my build. error message is: +# ../qt-5.1/include/QtCore/qglobal.h:975:4: error: #error "You must build your code with position independent code if Qt was built with -reduce-relocations. " "Compile your code with -fPIC or -fPIE." +# +add_definitions(-fPIC) diff --git a/CMake/mitkMacroCreateModule.cmake b/CMake/mitkMacroCreateModule.cmake index ca54646499..6499efbabd 100644 --- a/CMake/mitkMacroCreateModule.cmake +++ b/CMake/mitkMacroCreateModule.cmake @@ -1,428 +1,429 @@ ################################################################## # # MITK_CREATE_MODULE # #! Creates a module for the automatic module dependency system within MITK. #! Configurations are generated in the moduleConf directory. #! #! USAGE: #! #! \code #! MITK_CREATE_MODULE( #! [INCLUDE_DIRS ] #! [INTERNAL_INCLUDE_DIRS ] #! [DEPENDS ] #! [PACKAGE_DEPENDS ] #! [TARGET_DEPENDS #! [EXPORT_DEFINE ] #! [QT_MODULE] #! [HEADERS_ONLY] #! [WARNINGS_AS_ERRORS] #! \endcode #! #! \param MODULE_NAME_IN The name for the new module #! \param HEADERS_ONLY specify this if the modules just contains header files. ################################################################## macro(MITK_CREATE_MODULE MODULE_NAME_IN) set(_macro_params SUBPROJECTS # list of CDash labels VERSION # module version number, e.g. "1.2.0" INCLUDE_DIRS # exported include dirs (used in mitkMacroCreateModuleConf.cmake) INTERNAL_INCLUDE_DIRS # include dirs internal to this module DEPENDS # list of modules this module depends on DEPENDS_INTERNAL # list of modules this module internally depends on PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.) TARGET_DEPENDS # list of CMake targets this module should depend on EXPORT_DEFINE # export macro name for public symbols of this module AUTOLOAD_WITH # a module target name identifying the module which will trigger the # automatic loading of this module ADDITIONAL_LIBS # list of addidtional libraries linked to this module GENERATED_CPP # not used (?) ) set(_macro_options QT_MODULE # the module makes use of Qt features and needs moc and ui generated files 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_INIT # do not create CppMicroServices initialization code WARNINGS_AS_ERRORS # treat all compiler warnings as errors ) MACRO_PARSE_ARGUMENTS(MODULE "${_macro_params}" "${_macro_options}" ${ARGN}) set(MODULE_NAME ${MODULE_NAME_IN}) if(MODULE_HEADERS_ONLY) set(MODULE_PROVIDES ) if(MODULE_AUTOLOAD_WITH) message(SEND_ERROR "A headers only module cannot be auto-loaded") endif() else() set(MODULE_PROVIDES ${MODULE_NAME}) if(NOT MODULE_NO_INIT AND NOT MODULE_NAME STREQUAL "Mitk") # Add a dependency to the "Mitk" module #list(APPEND MODULE_DEPENDS Mitk) endif() endif() if(NOT MODULE_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) 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 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() # create a meta-target if it does not already exist set(_module_autoload_meta_target "${MODULE_AUTOLOAD_WITH}-universe") if(NOT TARGET ${_module_autoload_meta_target}) add_custom_target(${_module_autoload_meta_target}) endif() endif() # 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 AND NOT (MODULE_QT_MODULE AND NOT MITK_USE_QT)) # first of all we check for the dependencies MITK_CHECK_MODULE(_MISSING_DEP ${MODULE_DEPENDS}) if(_MISSING_DEP) message("Module ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") set(MODULE_IS_ENABLED 0) else(_MISSING_DEP) set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${MODULE_PACKAGE_DEPENDS}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("Module ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) endif() endforeach() 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_MOC_CPP ) set(Q${KITNAME}_GENERATED_QRC_CPP ) set(Q${KITNAME}_GENERATED_UI_CPP ) _MITK_CREATE_MODULE_CONF() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif(NOT MODULE_EXPORT_DEFINE) 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) set(DEPENDS "${MODULE_DEPENDS}") if(NOT MODULE_NO_INIT) # Add a CppMicroServices dependency implicitly, since it is # needed for the generated "module initialization" code. set(DEPENDS "CppMicroServices;${DEPENDS}") endif() set(DEPENDS_BEFORE "not initialized") set(PACKAGE_DEPENDS "${MODULE_PACKAGE_DEPENDS}") MITK_USE_MODULE(${DEPENDS}) # ok, now create the module itself include_directories(. ${ALL_INCLUDE_DIRECTORIES}) include(files.cmake) 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) set(use_visibility_flags 0) else() # We only support hidden visibility for gcc for now. Clang 3.0 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 if(CMAKE_COMPILER_IS_GNUCXX) set(use_visibility_flags 1) else() # set(use_visibility_flags 0) endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) # MinGW does not export all symbols automatically, so no need to set flags. # # With gcc < 4.5, RTTI symbols from classes declared in third-party libraries # which are not "gcc visibility aware" are marked with hidden visibility in # DSOs which include the class declaration and which are compiled with # hidden visibility. This leads to dynamic_cast and exception handling problems. # While this problem could be worked around by sandwiching the include # directives for the third-party headers between "#pragma visibility push/pop" # statements, it is generally safer to just use default visibility with # gcc < 4.5. if(${GCC_VERSION} VERSION_LESS "4.5" OR MINGW) set(use_visibility_flags 0) endif() endif() if(use_visibility_flags) mitkFunctionCheckCAndCXXCompilerFlags("-fvisibility=hidden" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-fvisibility-inlines-hidden" module_c_flags module_cxx_flags) endif() configure_file(${MITK_SOURCE_DIR}/CMake/moduleExports.h.in ${CMAKE_BINARY_DIR}/${MODULES_CONF_DIRNAME}/${MODULE_NAME}Exports.h @ONLY) if(MODULE_WARNINGS_AS_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) # VNL headers throw a lot of these, not fixable for us at least in ITK 3 mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unused-parameter" module_c_flags module_cxx_flags) # Some DICOM header file in ITK mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=cast-align" module_c_flags module_cxx_flags) endif() endif(MODULE_WARNINGS_AS_ERRORS) if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) if(NOT MODULE_NO_INIT AND NOT MODULE_HEADERS_ONLY) set(MODULE_LIBNAME ${MODULE_PROVIDES}) usFunctionGenerateModuleInit(CPP_FILES NAME ${MODULE_NAME} LIBRARY_NAME ${MODULE_LIBNAME} DEPENDS ${MODULE_DEPENDS} ${MODULE_DEPENDS_INTERNAL} ${MODULE_PACKAGE_DEPENDS} #VERSION ${MODULE_VERSION} ) if(RESOURCE_FILES) set(res_dir Resources) set(binary_res_files ) set(source_res_files ) 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() set(res_macro_args ) if(binary_res_files) list(APPEND res_macro_args ROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${res_dir} FILES ${binary_res_files}) endif() if(source_res_files) list(APPEND res_macro_args ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir} FILES ${source_res_files}) endif() usFunctionEmbedResources(CPP_FILES LIBRARY_NAME ${MODULE_LIBNAME} ${res_macro_args}) endif() endif() if(MODULE_QT_MODULE) + # TODO: here we would need handling of both Qt 4 and Qt 5 if(UI_FILES) QT4_WRAP_UI(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif(UI_FILES) if(MOC_H_FILES) QT4_WRAP_CPP(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) endif(MOC_H_FILES) if(QRC_FILES) QT4_ADD_RESOURCES(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif(QRC_FILES) set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) endif() ORGANIZE_SOURCES(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() if(NOT MODULE_HEADERS_ONLY) if(ALL_LIBRARY_DIRS) # LINK_DIRECTORIES applies only to targets which are added after the call to LINK_DIRECTORIES link_directories(${ALL_LIBRARY_DIRS}) endif(ALL_LIBRARY_DIRS) add_library(${MODULE_PROVIDES} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_PROVIDES} ${MODULE_TARGET_DEPENDS}) endif() if(MODULE_SUBPROJECTS) set_property(TARGET ${MODULE_PROVIDES} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_PROVIDES}) endforeach() endif() if(ALL_LIBRARIES) target_link_libraries(${MODULE_PROVIDES} ${ALL_LIBRARIES}) endif(ALL_LIBRARIES) if(MODULE_QT_MODULE AND QT_LIBRARIES) target_link_libraries(${MODULE_PROVIDES} ${QT_LIBRARIES}) endif() if(MINGW) target_link_libraries(${MODULE_PROVIDES} ssp) # add stack smash protection lib endif() # Apply properties to the module target. # We cannot use set_target_properties like below since there is no way to # differentiate C/C++ and Releas/Debug flags using target properties. # See http://www.cmake.org/Bug/view.php?id=6493 #set_target_properties(${MODULE_PROVIDES} PROPERTIES # COMPILE_FLAGS "${module_compile_flags}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${module_c_flags}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${module_c_flags_debug}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${module_c_flags_release}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${module_cxx_flags}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${module_cxx_flags_debug}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${module_cxx_flags_release}") # 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) 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_PROVIDES}) if(MODULE_AUTOLOAD_WITH) # for auto-loaded modules, adapt the output directory add_dependencies(${_module_autoload_meta_target} ${MODULE_PROVIDES}) 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_PROVIDES} PROPERTIES ${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH}) else() set_target_properties(${MODULE_PROVIDES} PROPERTIES ${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) endif() set_target_properties(${MODULE_PROVIDES} 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_PROVIDES}) else() # Add meta dependencies (e.g. on auto-load modules from depending modules) if(ALL_META_DEPENDENCIES) add_dependencies(${MODULE_PROVIDES} ${ALL_META_DEPENDENCIES}) endif() endif() endif() endif(MODULE_IS_ENABLED) endif(_MISSING_DEP) endif(NOT MODULE_IS_EXCLUDED AND NOT (MODULE_QT_MODULE AND NOT MITK_USE_QT)) if(NOT MODULE_IS_ENABLED) _MITK_CREATE_MODULE_CONF() endif(NOT MODULE_IS_ENABLED) endmacro(MITK_CREATE_MODULE) diff --git a/Core/Code/DataManagement/mitkTimeSlicedGeometry.cpp b/Core/Code/DataManagement/mitkTimeSlicedGeometry.cpp index 2b29716886..90f0256d78 100644 --- a/Core/Code/DataManagement/mitkTimeSlicedGeometry.cpp +++ b/Core/Code/DataManagement/mitkTimeSlicedGeometry.cpp @@ -1,422 +1,423 @@ /*=================================================================== 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 "mitkTimeSlicedGeometry.h" void mitk::TimeSlicedGeometry::UpdateInformation() { if(m_TimeSteps==0) return; unsigned long maxModifiedTime = 0, curModifiedTime; mitk::ScalarType stmin, stmax; stmin= ScalarTypeNumericTraits::NonpositiveMin(); stmax= ScalarTypeNumericTraits::max(); TimeBounds timeBounds; timeBounds[0]=stmax; timeBounds[1]=stmin; mitk::BoundingBox::Pointer boundingBox=mitk::BoundingBox::New(); mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New(); unsigned int t; mitk::Geometry3D* geometry3d; mitk::BoundingBox::ConstPointer nextBoundingBox; mitk::BoundingBox::PointIdentifier pointid=0; // Need to check for zero bounding boxes mitk::ScalarType zeropoint[]={0,0,0,0,0,0}; BoundingBox::BoundsArrayType itkBoundsZero(zeropoint); for(t=0; t < m_TimeSteps; ++t) { geometry3d = GetGeometry3D(t); assert(geometry3d!=NULL); curModifiedTime = geometry3d->GetMTime(); if(maxModifiedTime < curModifiedTime) maxModifiedTime = curModifiedTime; const TimeBounds & curTimeBounds = geometry3d->GetTimeBounds(); if((curTimeBounds[0] > stmin) && (curTimeBounds[0] < timeBounds[0])) timeBounds[0] = curTimeBounds[0]; if((curTimeBounds[1] < stmax) && (curTimeBounds[1] > timeBounds[1])) timeBounds[1] = curTimeBounds[1]; nextBoundingBox = geometry3d->GetBoundingBox(); assert(nextBoundingBox.IsNotNull()); // Only respect non-zero BBes if (nextBoundingBox->GetBounds() == itkBoundsZero) { continue; } const mitk::BoundingBox::PointsContainer * nextPoints = nextBoundingBox->GetPoints(); if(nextPoints!=NULL) { mitk::BoundingBox::PointsContainer::ConstIterator pointsIt = nextPoints->Begin(); while (pointsIt != nextPoints->End() ) { pointscontainer->InsertElement( pointid++, pointsIt->Value()); ++pointsIt; } } } if(!(timeBounds[0] < stmax)) { timeBounds[0] = stmin; timeBounds[1] = stmax; } m_TimeBounds = timeBounds; assert(timeBounds[0]<=timeBounds[1]); boundingBox->SetPoints(pointscontainer); boundingBox->ComputeBoundingBox(); m_BoundingBox = boundingBox; SetIndexToWorldTransform(GetGeometry3D(0)->GetIndexToWorldTransform()); if(this->GetMTime() < maxModifiedTime) Modified(); } mitk::Geometry3D* mitk::TimeSlicedGeometry::GetGeometry3D(int t) const { mitk::Geometry3D::Pointer geometry3d = NULL; if(IsValidTime(t)) { geometry3d = m_Geometry3Ds[t]; //if (a) we don't have a Geometry3D stored for the requested time, //(b) m_EvenlyTimed is activated and (c) the first geometry (t=0) //is set, then we clone the geometry and set the m_TimeBounds accordingly. - if((m_EvenlyTimed) && (geometry3d.IsNull())) + if((m_EvenlyTimed) && (geometry3d.IsNull()) && m_Geometry3Ds[0].IsNotNull()) { const Geometry3D* firstgeometry=m_Geometry3Ds[0].GetPointer(); - assert(firstgeometry != NULL); - mitk::Geometry3D::Pointer requestedgeometry; requestedgeometry = dynamic_cast(firstgeometry->Clone().GetPointer()); if ( requestedgeometry.IsNull() ) itkExceptionMacro("Geometry is NULL!"); TimeBounds timebounds = requestedgeometry->GetTimeBounds(); if(timebounds[1]SetTimeBounds(timebounds); } geometry3d = requestedgeometry; m_Geometry3Ds[t] = geometry3d; } } else + { return NULL; + } + return geometry3d; } bool mitk::TimeSlicedGeometry::SetGeometry3D(mitk::Geometry3D* geometry3D, int t) { if(IsValidTime(t)) { m_Geometry3Ds[t]=geometry3D; return true; } return false; } int mitk::TimeSlicedGeometry::MSToTimeStep(mitk::ScalarType time_in_ms) const { if(time_in_ms < m_TimeBounds[0]) return -1; if(time_in_ms >= m_TimeBounds[1]) return m_TimeSteps; if(m_EvenlyTimed) { if(m_TimeBounds[0] == m_TimeBounds[1]) return 0; if((m_TimeBounds[0]>ScalarTypeNumericTraits::NonpositiveMin()) && (m_TimeBounds[1]GetTimeBounds(); if( (timeBounds[0] <= time_in_ms) && (time_in_ms <= timeBounds[1]) ) { return t; } } } return 0; } mitk::ScalarType mitk::TimeSlicedGeometry::TimeStepToMS(int timestep) const { if(IsValidTime(timestep)==false) return ScalarTypeNumericTraits::max(); if(m_EvenlyTimed) { if ( timestep == 0 ) return m_TimeBounds[0]; else { assert( ! (m_TimeBounds[0] == ScalarTypeNumericTraits::NonpositiveMin() && m_TimeBounds[1] == ScalarTypeNumericTraits::max() ) ); return ((mitk::ScalarType)timestep)/m_TimeSteps*(m_TimeBounds[1]-m_TimeBounds[0])+m_TimeBounds[0]; } } else { return GetGeometry3D(timestep)->GetTimeBounds()[0]; } } int mitk::TimeSlicedGeometry::TimeStepToTimeStep( const mitk::TimeSlicedGeometry *referenceGeometry, int t) const { int timeStep; if ( referenceGeometry->GetTimeSteps() > 1 ) { // referenceGeometry is nD+t timeStep = this->MSToTimeStep( referenceGeometry->TimeStepToMS( t ) ); } else { // referenceGEometry is nD (only one time step) timeStep = 0; } return timeStep; } void mitk::TimeSlicedGeometry::InitializeEvenlyTimed(unsigned int timeSteps) { Geometry3D::Pointer geometry3D = Geometry3D::New(); geometry3D->Initialize(); InitializeEvenlyTimed(geometry3D, timeSteps); } void mitk::TimeSlicedGeometry::InitializeEvenlyTimed(mitk::Geometry3D* geometry3D, unsigned int timeSteps) { assert(geometry3D!=NULL); geometry3D->Register(); InitializeEmpty(timeSteps); AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetMatrix(geometry3D->GetIndexToWorldTransform()->GetMatrix()); transform->SetOffset(geometry3D->GetIndexToWorldTransform()->GetOffset()); SetIndexToWorldTransform(transform); SetBounds(geometry3D->GetBounds()); SetGeometry3D(geometry3D, 0); SetEvenlyTimed(); UpdateInformation(); SetFrameOfReferenceID(geometry3D->GetFrameOfReferenceID()); SetImageGeometry(geometry3D->GetImageGeometry()); geometry3D->UnRegister(); } void mitk::TimeSlicedGeometry::InitializeEmpty(unsigned int timeSteps) { m_IndexToWorldTransform = NULL; Superclass::Initialize(); m_TimeSteps = timeSteps; // initialize with empty geometries Geometry3D::Pointer gnull=NULL; m_Geometry3Ds.assign(m_TimeSteps, gnull); } void mitk::TimeSlicedGeometry::ExpandToNumberOfTimeSteps( unsigned int timeSteps ) { if( timeSteps <= m_TimeSteps ) return; if(m_TimeSteps == 1) { Geometry3D* g3d = m_Geometry3Ds[0]; const TimeBounds & timeBounds = g3d->GetTimeBounds(); if( (timeBounds[0] == ScalarTypeNumericTraits::NonpositiveMin()) || (timeBounds[1]==ScalarTypeNumericTraits::max()) ) { mitk::ScalarType timeBounds[] = {0.0, 1.0}; m_Geometry3Ds[0]->SetTimeBounds( timeBounds ); } } // Expand to Number of time steps; initialize with empty geometries Geometry3D::Pointer gnull=NULL; m_Geometry3Ds.resize(timeSteps, gnull); m_TimeSteps = timeSteps; UpdateInformation(); } mitk::TimeSlicedGeometry::TimeSlicedGeometry() : m_TimeSteps(0), m_EvenlyTimed(false) { } mitk::TimeSlicedGeometry::TimeSlicedGeometry(const TimeSlicedGeometry& other) : Geometry3D(other), m_TimeSteps(other.m_TimeSteps), m_EvenlyTimed(other.m_EvenlyTimed) { m_Geometry3Ds.resize(m_TimeSteps); unsigned int t; for(t=0; t(other.m_Geometry3Ds[t]->Clone().GetPointer()), t); } } } mitk::TimeSlicedGeometry::~TimeSlicedGeometry() { } void mitk::TimeSlicedGeometry::SetImageGeometry(const bool isAnImageGeometry) { Superclass::SetImageGeometry(isAnImageGeometry); mitk::Geometry3D* geometry3d; unsigned int t; for(t=0; tSetImageGeometry(isAnImageGeometry); } } void mitk::TimeSlicedGeometry::ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry) { mitk::Geometry3D* geometry3d; unsigned int t; for(t=0; tChangeImageGeometryConsideringOriginOffset(isAnImageGeometry); } Superclass::ChangeImageGeometryConsideringOriginOffset(isAnImageGeometry); } void mitk::TimeSlicedGeometry::SetEvenlyTimed(bool on) { m_EvenlyTimed = on; Modified(); } bool mitk::TimeSlicedGeometry::IsValidTime(int t) const { return (t>=0) && (t< (int)m_TimeSteps); } bool mitk::TimeSlicedGeometry::IsValid() const { return Superclass::IsValid() && (m_TimeSteps > 0); } void mitk::TimeSlicedGeometry::CopyTimes(const mitk::TimeSlicedGeometry* timeslicedgeometry, unsigned int t, unsigned int endtimeindex) { if(endtimeindex >= timeslicedgeometry->GetTimeSteps()) endtimeindex = timeslicedgeometry->GetTimeSteps()-1; if(endtimeindex >= this->GetTimeSteps()) endtimeindex = this->GetTimeSteps()-1; for(; t <= endtimeindex; ++t) { mitk::Geometry3D* geometry3d = GetGeometry3D(t); mitk::Geometry3D* othergeometry3d = timeslicedgeometry->GetGeometry3D(t); assert((geometry3d!=NULL) && (othergeometry3d!=NULL)); geometry3d->SetTimeBounds(othergeometry3d->GetTimeBounds()); } UpdateInformation(); } itk::LightObject::Pointer mitk::TimeSlicedGeometry::InternalClone() const { Self::Pointer newGeometry = new TimeSlicedGeometry(*this); newGeometry->UnRegister(); return newGeometry.GetPointer(); } void mitk::TimeSlicedGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const { //Superclass::PrintSelf(os,indent); os << indent << " EvenlyTimed: " << m_EvenlyTimed << std::endl; os << indent << " TimeSteps: " << m_TimeSteps << std::endl; os << std::endl; os << indent << " GetGeometry3D(0): "; if(GetGeometry3D(0)==NULL) os << "NULL" << std::endl; else GetGeometry3D(0)->Print(os, indent); } void mitk::TimeSlicedGeometry::ExecuteOperation(Operation* operation) { // reach through to all time steps for (std::vector::iterator iter = m_Geometry3Ds.begin(); iter != m_Geometry3Ds.end(); ++iter) { (*iter)->ExecuteOperation(operation); } Geometry3D::ExecuteOperation(operation); this->Modified(); } diff --git a/Core/Code/Interactions/mitkDispatcher.cpp b/Core/Code/Interactions/mitkDispatcher.cpp index 333667723c..ccc3bf06a6 100644 --- a/Core/Code/Interactions/mitkDispatcher.cpp +++ b/Core/Code/Interactions/mitkDispatcher.cpp @@ -1,250 +1,250 @@ /*=================================================================== 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 "mitkDispatcher.h" #include "mitkInteractionEvent.h" #include "mitkInternalEvent.h" // MicroServices #include "usGetModuleContext.h" #include "mitkInteractionEventObserver.h" mitk::Dispatcher::Dispatcher( const std::string& rendererName ) : m_ProcessingMode(REGULAR) { // LDAP filter string to find all listeners specific for the renderer // corresponding to this dispatcher std::string specificRenderer = "(rendererName=" + rendererName +")"; // LDAP filter string to find all listeners that are not specific // to any renderer std::string anyRenderer = "(!(rendererName=*))"; // LDAP filter string to find only instances of InteractionEventObserver std::string classInteractionEventObserver = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")"; // Configure the LDAP filter to find all instances of InteractionEventObserver // that are specific to this dispatcher or unspecific to any dispatchers (real global listener) us::LDAPFilter filter( "(&(|"+ specificRenderer + anyRenderer + ")"+classInteractionEventObserver+")" ); // Give the filter to the ObserverTracker m_EventObserverTracker = new us::ServiceTracker(us::GetModuleContext(), filter); m_EventObserverTracker->Open(); } void mitk::Dispatcher::AddDataInteractor(const DataNode* dataNode) { RemoveDataInteractor(dataNode); RemoveOrphanedInteractors(); DataInteractor::Pointer dataInteractor = dataNode->GetDataInteractor(); if (dataInteractor.IsNotNull()) { m_Interactors.push_back(dataInteractor); } } /* * Note: One DataInteractor can only have one DataNode and vice versa, * BUT the m_Interactors list may contain another DataInteractor that is still connected to this DataNode, * in this case we have to remove >1 DataInteractor. (Some special case of switching DataNodes between DataInteractors and registering a * DataNode to a DataStorage after assigning it to an DataInteractor) */ void mitk::Dispatcher::RemoveDataInteractor(const DataNode* dataNode) { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { if ((*it)->GetDataNode() == dataNode) { it = m_Interactors.erase(it); } else { ++it; } } } size_t mitk::Dispatcher::GetNumberOfInteractors() { return m_Interactors.size(); } mitk::Dispatcher::~Dispatcher() { m_EventObserverTracker->Close(); delete m_EventObserverTracker; m_Interactors.clear(); } bool mitk::Dispatcher::ProcessEvent(InteractionEvent* event) { InteractionEvent::Pointer p = event; - //MITK_INFO << event->GetEventClass(); + bool eventIsHandled = false; /* Filter out and handle Internal Events separately */ InternalEvent* internalEvent = dynamic_cast(event); if (internalEvent != NULL) { eventIsHandled = HandleInternalEvent(internalEvent); // InternalEvents that are handled are not sent to the listeners if (eventIsHandled) { return true; } } switch (m_ProcessingMode) { case CONNECTEDMOUSEACTION: // finished connected mouse action if (std::strcmp(p->GetNameOfClass(), "MouseReleaseEvent") == 0) { m_ProcessingMode = REGULAR; eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } // give event to selected interactor if (eventIsHandled == false) { eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } break; case GRABINPUT: eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); SetEventProcessingMode(m_SelectedInteractor); break; case PREFERINPUT: if (m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()) == true) { SetEventProcessingMode(m_SelectedInteractor); eventIsHandled = true; } break; case REGULAR: break; } // Standard behavior. Is executed in STANDARD mode and PREFERINPUT mode, if preferred interactor rejects event. if (m_ProcessingMode == REGULAR || (m_ProcessingMode == PREFERINPUT && eventIsHandled == false)) { m_Interactors.sort(cmp()); // sorts interactors by layer (descending); // copy the list to prevent iterator invalidation as executing actions // in HandleEvent() can cause the m_Interactors list to be updated std::list tmpInteractorList( m_Interactors ); std::list::iterator it; for ( it=tmpInteractorList.begin(); it!=tmpInteractorList.end(); it++ ) { DataInteractor::Pointer dataInteractor = *it; if ( (*it)->HandleEvent(event, dataInteractor->GetDataNode()) ) { // if an event is handled several properties are checked, in order to determine the processing mode of the dispatcher SetEventProcessingMode(dataInteractor); if (std::strcmp(p->GetNameOfClass(), "MousePressEvent") == 0 && m_ProcessingMode == REGULAR) { m_SelectedInteractor = dataInteractor; m_ProcessingMode = CONNECTEDMOUSEACTION; } eventIsHandled = true; break; } } } /* Notify InteractionEventObserver */ std::vector > listEventObserver = m_EventObserverTracker->GetServiceReferences(); for (std::vector >::iterator it = listEventObserver.begin(); it != listEventObserver.end(); ++it) { InteractionEventObserver* interactionEventObserver = m_EventObserverTracker->GetService(*it); if (interactionEventObserver != NULL) { if (interactionEventObserver->IsEnabled()) { interactionEventObserver->Notify(event, eventIsHandled); } } } // Process event queue if (!m_QueuedEvents.empty()) { InteractionEvent::Pointer e = m_QueuedEvents.front(); m_QueuedEvents.pop_front(); ProcessEvent(e); } return eventIsHandled; } /* * Checks if DataNodes associated with DataInteractors point back to them. * If not remove the DataInteractors. (This can happen when s.o. tries to set DataNodes to multiple DataInteractors) */ void mitk::Dispatcher::RemoveOrphanedInteractors() { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { DataNode::Pointer dn = (*it)->GetDataNode(); if (dn.IsNull()) { it = m_Interactors.erase(it); } else { DataInteractor::Pointer interactor = dn->GetDataInteractor(); if (interactor != it->GetPointer()) { it = m_Interactors.erase(it); } else { ++it; } } } } void mitk::Dispatcher::QueueEvent(InteractionEvent* event) { m_QueuedEvents.push_back(event); } void mitk::Dispatcher::SetEventProcessingMode(DataInteractor::Pointer dataInteractor) { m_ProcessingMode = dataInteractor->GetMode(); if (dataInteractor->GetMode() != REGULAR) { m_SelectedInteractor = dataInteractor; } } bool mitk::Dispatcher::HandleInternalEvent(InternalEvent* internalEvent) { if (internalEvent->GetSignalName() == DataInteractor::IntDeactivateMe && internalEvent->GetTargetInteractor() != NULL) { internalEvent->GetTargetInteractor()->GetDataNode()->SetDataInteractor(NULL); internalEvent->GetTargetInteractor()->SetDataNode(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } diff --git a/Core/Code/Rendering/mitkRenderWindow.cpp b/Core/Code/Rendering/mitkRenderWindow.cpp index 7ce3824b23..3cdacc6baa 100644 --- a/Core/Code/Rendering/mitkRenderWindow.cpp +++ b/Core/Code/Rendering/mitkRenderWindow.cpp @@ -1,88 +1,90 @@ /*=================================================================== 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 "mitkRenderWindow.h" #include "mitkDisplayPositionEvent.h" #include "mitkVtkLayerController.h" #include "mitkRenderingManager.h" #include "vtkRenderer.h" #include "vtkRenderWindowInteractor.h" #include "mitkVtkEventProvider.h" mitk::RenderWindow::RenderWindow(vtkRenderWindow* renWin, const char* name, mitk::RenderingManager* rm ) : m_vtkRenderWindow(renWin) +, m_vtkRenderWindowInteractor(NULL) +, m_vtkMitkEventProvider(NULL) { if(m_vtkRenderWindow == NULL) m_vtkRenderWindow = vtkRenderWindow::New(); if ( m_vtkRenderWindow->GetSize()[0] <= 10 || m_vtkRenderWindow->GetSize()[0] <= 10 ) { m_vtkRenderWindow->SetSize( 100, 100 ); } m_vtkRenderWindowInteractor = vtkRenderWindowInteractor::New(); m_vtkRenderWindowInteractor->SetRenderWindow(m_vtkRenderWindow); m_vtkRenderWindowInteractor->Initialize(); // initialize from RenderWindowBase Initialize(rm,name); m_vtkMitkEventProvider = vtkEventProvider::New(); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } mitk::RenderWindow::~RenderWindow() { Destroy(); m_vtkRenderWindow->Delete(); m_vtkRenderWindowInteractor->Delete(); m_vtkMitkEventProvider->Delete(); } vtkRenderWindow* mitk::RenderWindow::GetVtkRenderWindow() { return m_vtkRenderWindow; } vtkRenderWindowInteractor* mitk::RenderWindow::GetVtkRenderWindowInteractor() { return m_vtkRenderWindowInteractor; } void mitk::RenderWindow::SetSize( int width, int height ) { this->GetVtkRenderWindow()->SetSize( width, height ); this->resizeMitkEvent( width, height ); } void mitk::RenderWindow::ReinitEventProvider() { m_vtkMitkEventProvider->SetEnabled(0); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } diff --git a/Core/Code/Rendering/mitkRenderWindowBase.cpp b/Core/Code/Rendering/mitkRenderWindowBase.cpp index 0e66581227..a9813143bc 100644 --- a/Core/Code/Rendering/mitkRenderWindowBase.cpp +++ b/Core/Code/Rendering/mitkRenderWindowBase.cpp @@ -1,163 +1,165 @@ /*=================================================================== 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 "mitkRenderWindowBase.h" #include "mitkDisplayPositionEvent.h" #include "mitkVtkLayerController.h" #include "mitkRenderingManager.h" #include "vtkRenderer.h" mitk::RenderWindowBase::RenderWindowBase( ) +: m_RenderProp(NULL) +, m_InResize(false) { } /* * "Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a * virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from * a destructor, and the object to which the call applies is the object under construction or destruction, the function called is * the one defined in the constructor or destructor�s own class or in one of its bases, but not a function overriding it in a class * derived from the constructor or destructor�s class, or overriding it in one of the other base classes of the most derived object[..]" * or short: within constructors and destructors classes are not polymorph. */ void mitk::RenderWindowBase::Initialize( mitk::RenderingManager* renderingManager, const char* name ) { if ( renderingManager == NULL ) { renderingManager = mitk::RenderingManager::GetInstance(); } if(m_Renderer.IsNull()) { m_Renderer = mitk::VtkPropRenderer::New( name , GetVtkRenderWindow(), renderingManager ); } m_Renderer->InitRenderer(this->GetVtkRenderWindow()); mitk::BaseRenderer::AddInstance(GetVtkRenderWindow(),m_Renderer); renderingManager->AddRenderWindow(GetVtkRenderWindow()); m_RenderProp = vtkMitkRenderProp::New(); m_RenderProp->SetPropRenderer(m_Renderer); m_Renderer->GetVtkRenderer()->AddViewProp(m_RenderProp); if((this->GetVtkRenderWindow()->GetSize()[0] > 10) && (this->GetVtkRenderWindow()->GetSize()[1] > 10)) m_Renderer->InitSize(this->GetVtkRenderWindow()->GetSize()[0], this->GetVtkRenderWindow()->GetSize()[1]); m_InResize = false; } bool mitk::RenderWindowBase::HandleEvent(InteractionEvent* interactionEvent) { return m_Renderer->GetDispatcher()->ProcessEvent(interactionEvent); } void mitk::RenderWindowBase::Destroy() { m_Renderer->GetRenderingManager()->RemoveRenderWindow(GetVtkRenderWindow()); mitk::BaseRenderer::RemoveInstance(GetVtkRenderWindow()); m_Renderer->GetVtkRenderer()->RemoveViewProp(m_RenderProp); m_RenderProp->Delete(); } mitk::RenderWindowBase::~RenderWindowBase() { } void mitk::RenderWindowBase::mousePressMitkEvent(mitk::MouseEvent *me) { if (m_Renderer.IsNotNull()) m_Renderer->MousePressEvent(me); } void mitk::RenderWindowBase::mouseReleaseMitkEvent(mitk::MouseEvent *me) { if(m_Renderer.IsNotNull()) m_Renderer->MouseReleaseEvent(me); } void mitk::RenderWindowBase::mouseMoveMitkEvent(mitk::MouseEvent *me) { if (m_Renderer.IsNotNull()) m_Renderer->MouseMoveEvent(me); } void mitk::RenderWindowBase::wheelMitkEvent(mitk::WheelEvent *we) { if(m_Renderer.IsNotNull()) { m_Renderer->WheelEvent(we); } } void mitk::RenderWindowBase::keyPressMitkEvent(mitk::KeyEvent* mke) { if (m_Renderer.IsNotNull()) m_Renderer->KeyPressEvent(mke); } void mitk::RenderWindowBase::resizeMitkEvent(int width, int height) { if(m_InResize) //@FIXME CRITICAL probably related to VtkSizeBug return; m_InResize = true; if(m_Renderer.IsNotNull()) { m_Renderer->Resize(width, height); } m_InResize = false; } mitk::SliceNavigationController * mitk::RenderWindowBase::GetSliceNavigationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetSliceNavigationController(); } mitk::CameraRotationController * mitk::RenderWindowBase::GetCameraRotationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetCameraRotationController(); } mitk::BaseController * mitk::RenderWindowBase::GetController() { mitk::BaseRenderer * renderer = mitk::BaseRenderer::GetInstance(GetVtkRenderWindow()); switch ( renderer->GetMapperID() ) { case mitk::BaseRenderer::Standard2D: return GetSliceNavigationController(); case mitk::BaseRenderer::Standard3D: return GetCameraRotationController(); default: return GetSliceNavigationController(); } } mitk::VtkPropRenderer* mitk::RenderWindowBase::GetRenderer() { return m_Renderer; } diff --git a/Core/Code/Rendering/vtkMitkRenderProp.cpp b/Core/Code/Rendering/vtkMitkRenderProp.cpp index 59d4c6bf9d..f7e01a3ea2 100644 --- a/Core/Code/Rendering/vtkMitkRenderProp.cpp +++ b/Core/Code/Rendering/vtkMitkRenderProp.cpp @@ -1,107 +1,112 @@ /*=================================================================== 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 "vtkMitkRenderProp.h" #include #include #include #include "mitkVtkMapper.h" #include "mitkGLMapper.h" vtkStandardNewMacro(vtkMitkRenderProp); vtkMitkRenderProp::vtkMitkRenderProp() { } vtkMitkRenderProp::~vtkMitkRenderProp() { } double *vtkMitkRenderProp::GetBounds() { return const_cast(m_VtkPropRenderer->GetBounds()); } void vtkMitkRenderProp::SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer) { this->m_VtkPropRenderer = propRenderer; } int vtkMitkRenderProp::RenderOpaqueGeometry(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Opaque); } int vtkMitkRenderProp::RenderOverlay(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Overlay); } void vtkMitkRenderProp::ReleaseGraphicsResources(vtkWindow* window) { m_VtkPropRenderer->ReleaseGraphicsResources(window); } void vtkMitkRenderProp::InitPathTraversal() { m_VtkPropRenderer->InitPathTraversal(); } vtkAssemblyPath* vtkMitkRenderProp::GetNextPath() { return m_VtkPropRenderer->GetNextPath(); } //BUG (#1551) added method depth peeling int vtkMitkRenderProp::HasTranslucentPolygonalGeometry() { + return 0; /* If I don't deactivate this function, I get lots of output like + + ERROR: In /home/maleike/build/mitk2/VTK-src/Rendering/vtkLODProp3D.cxx, line 969 + vtkLODProp3D (0x7f810452f000): Index out of range! + */ typedef std::map MappersMapType; MappersMapType mappersMap = m_VtkPropRenderer->GetMappersMap(); for(MappersMapType::iterator it = mappersMap.begin(); it != mappersMap.end(); it++) { mitk::Mapper * mapper = (*it).second; mitk::VtkMapper::Pointer vtkMapper = dynamic_cast(mapper); if(vtkMapper) { // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly // manually (see issue #8186 committed to VTK's Mantis issue tracker) // --> VTK bug resolved on 2008-12-01 vtkPropAssembly *propAssembly = dynamic_cast< vtkPropAssembly * >( vtkMapper->GetVtkProp(m_VtkPropRenderer) ); if ( propAssembly ) { propAssembly->InitPathTraversal(); } if (vtkMapper->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) return 1; } } return 0; } int vtkMitkRenderProp::RenderTranslucentPolygonalGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Translucent); } int vtkMitkRenderProp::RenderVolumetricGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Volumetric); } diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index d98c4fd9ca..76ed56def0 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,66 +1,67 @@ set(MITK_DEFAULT_SUBPROJECTS MITK-Examples) #----------------------------------------------------------------------------- # Set-up example plugins #----------------------------------------------------------------------------- if(MITK_USE_BLUEBERRY) # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_example_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk OUTPUT_VARIABLE ${varname}) endmacro() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Plugins/${mitk_example_plugin}) endforeach() ctkMacroSetupPlugins(${mitk_example_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ COMPACT_OPTIONS) set(MITK_EXAMPLE_PLUGIN_TARGETS ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) ctkFunctionExtractOptionNameAndValue(${mitk_example_plugin} plugin_name plugin_value) string(REPLACE "." "_" _plugin_target ${plugin_name}) list(APPEND MITK_EXAMPLE_PLUGIN_TARGETS ${_plugin_target}) mark_as_advanced(${${_plugin_target}_option_name}) endforeach() endif() #----------------------------------------------------------------------------- # Add example executables #----------------------------------------------------------------------------- set(MITK_DIR ${PROJECT_BINARY_DIR}) set(MITK_EXPORTS_FILE_INCLUDED 1) set(_example_dirs MbiLog QtFreeRender - Overlays +# Overlays# depends on QmitkExt.. + QuickRender ) if(MITK_USE_QT) list(APPEND _example_dirs Tutorial QtAppExample ) endif() if(MITK_USE_BLUEBERRY) list(APPEND _example_dirs BlueBerryExampleLauncher ) endif() foreach(_example_dir ${_example_dirs}) add_subdirectory(${_example_dir}) endforeach() diff --git a/Examples/QuickRender/CMakeLists.txt b/Examples/QuickRender/CMakeLists.txt new file mode 100644 index 0000000000..ac371ba006 --- /dev/null +++ b/Examples/QuickRender/CMakeLists.txt @@ -0,0 +1,29 @@ +project(QuickRender) +find_package(MITK) + +# Check prerequisites for this application. +# We need the Mitk module. +MITK_CHECK_MODULE(result Mitk QmlMitk) +if(result) + message(SEND_ERROR "MITK module(s) \"${result}\" not available from the MITK build at ${MITK_DIR}") +endif() + +# Set-up the build system to use the Mitk module +MITK_USE_MODULE(Mitk QmlMitk) + +include_directories(${ALL_INCLUDE_DIRECTORIES}) +link_directories(${ALL_LIBRARY_DIRS}) + +# handle qt 5 classes +qt5_add_resources(rcc_SRC QuickRender.qrc) + +#add_executable(${PROJECT_NAME} QuickRender.cpp ${mocs_SRC}) +add_executable(${PROJECT_NAME} main.cpp ${moc_SRC} ${rcc_SRC}) +target_link_libraries(${PROJECT_NAME} ${ALL_LIBRARIES}) + +# subproject support +set_property(TARGET ${PROJECT_NAME} PROPERTY LABELS ${MITK_DEFAULT_SUBPROJECTS}) +foreach(subproject ${MITK_DEFAULT_SUBPROJECTS}) + add_dependencies(${subproject} ${PROJECT_NAME}) +endforeach() + diff --git a/Examples/QuickRender/QmlMitkFourRenderWindowWidget.qml b/Examples/QuickRender/QmlMitkFourRenderWindowWidget.qml new file mode 100644 index 0000000000..5dc152d6de --- /dev/null +++ b/Examples/QuickRender/QmlMitkFourRenderWindowWidget.qml @@ -0,0 +1,79 @@ +import QtQuick 2.0 +import QmlMitk 1.0 + +Item { + anchors.fill: parent + + QmlMitkRenderWindowItem { + id : renderwindownodeAxial + objectName : "mitkRenderItemAxial" + + anchors.left : parent.left + anchors.right : parent.horizontalCenter + anchors.top : parent.top + anchors.bottom : parent.verticalCenter + anchors.margins : 0 + } + + Rectangle { + color: Qt.rgba(1, 1, 1, 0.0) + radius: 1; border.width: 3; border.color: "red" + anchors.fill: renderwindownodeAxial + } + + + QmlMitkRenderWindowItem { + id : renderwindownodeSagittal + objectName : "mitkRenderItemSagittal" + + anchors.left : parent.horizontalCenter + anchors.right : parent.right + anchors.top : parent.top + anchors.bottom : parent.verticalCenter + anchors.margins : 0 + + } + + Rectangle { + color: Qt.rgba(1, 1, 1, 0.0) + radius: 1; border.width: 3; border.color: "green" + anchors.fill: renderwindownodeSagittal + } + + QmlMitkRenderWindowItem { + id : renderwindownodeFrontal + objectName : "mitkRenderItemFrontal" + + anchors.left : parent.left + anchors.right : parent.horizontalCenter + anchors.top : parent.verticalCenter + anchors.bottom : parent.bottom + anchors.margins : 0 + + } + + Rectangle { + color: Qt.rgba(1, 1, 1, 0.0) + radius: 1; border.width: 3; border.color: "blue" + anchors.fill: renderwindownodeFrontal + } + + QmlMitkRenderWindowItem { + id : renderwindownode3D + objectName : "mitkRenderItem3D" + + anchors.left : parent.horizontalCenter + anchors.right : parent.right + anchors.top : parent.verticalCenter + anchors.bottom : parent.bottom + anchors.margins : 0 + + } + + Rectangle { + color: Qt.rgba(1, 1, 1, 0.0) + radius: 1; border.width: 3; border.color: "yellow" + anchors.fill: renderwindownode3D + } + +} diff --git a/Examples/QuickRender/QuickRender.qml b/Examples/QuickRender/QuickRender.qml new file mode 100644 index 0000000000..528ca0648e --- /dev/null +++ b/Examples/QuickRender/QuickRender.qml @@ -0,0 +1,135 @@ +import QtQuick 2.0 +import QmlMitk 1.0 + +Item { + + width: 800 + height: 600 + + Rectangle { + id: topbar + + color: "papayawhip" + + height: 30 + + anchors.top : parent.top + anchors.left : parent.left + anchors.right : parent.right + } + + Rectangle { + id: leftbar + + color: "tomato" + + width: 40 + + anchors.left : parent.left + anchors.top : topbar.bottom + anchors.bottom : parent.bottom + } + + Rectangle { + id: rightbar + + color: "peachpuff" + + width: 40 + + anchors.right : parent.right + anchors.top : topbar.bottom + anchors.bottom : parent.bottom + } + + Rectangle { + id: bottombar + + color: "sandybrown" + + height: 15 + + anchors.bottom : parent.bottom + anchors.left : parent.left + anchors.right : parent.right + } + + + + QmlMitkFourRenderWindowWidget { + id : mitkMultiWidget + objectName : "mitkMultiWidget" + + anchors.left : leftbar.right + anchors.right : rightbar.left + anchors.top : topbar.bottom + anchors.bottom : bottombar.top + anchors.margins : 0 + } + + Rectangle + { + id: reactiveRect + color: "mintcream" + opacity: 0.8 + radius: 10 + border.width: 5 + border.color: "mintcream" + + width: 610 + height: 200 + + anchors.horizontalCenter: mitkMultiWidget.horizontalCenter + anchors.verticalCenter: mitkMultiWidget.verticalCenter + + rotation: 3 + + Text + { + id: label + color: "dodgerblue" + wrapMode: Text.WordWrap + font.pointSize: 16 + font.bold: true + text: "The background is a QmlMitkFourRenderWindowWidget\nwrapping four QmlMitkRenderWindowItems\nbased on QVTKQuickItem from OpenView.\nAll the colorful environment is a QML scene..." + + width: 590 + anchors.horizontalCenter: reactiveRect.horizontalCenter + anchors.verticalCenter: reactiveRect.verticalCenter + + rotation: 2 + + } + + MouseArea { id: mouseArea; anchors.fill: reactiveRect; hoverEnabled: true } + + // When the text is pressed, move, rotate and change the color to yellow. + states: State + { + name: "down"; when: mouseArea.containsMouse == true + + PropertyChanges + { + target: reactiveRect; rotation: -2; + } + + PropertyChanges + { + target: label; color: "deeppink"; rotation: -2 + } + } + + // How do we get from the implicit state to the down sate? + transitions: Transition + { + from: ""; to: "down"; reversible: true + + ParallelAnimation + { + NumberAnimation { properties: "y,rotation"; duration: 500; easing.type: Easing.InOutQuad } + ColorAnimation { duration: 500 } + } + } + } + +} diff --git a/Examples/QuickRender/QuickRender.qrc b/Examples/QuickRender/QuickRender.qrc new file mode 100644 index 0000000000..9753ba08dc --- /dev/null +++ b/Examples/QuickRender/QuickRender.qrc @@ -0,0 +1,8 @@ + + + QuickRender.qml + + + QmlMitkFourRenderWindowWidget.qml + + diff --git a/Examples/QuickRender/README.md b/Examples/QuickRender/README.md new file mode 100644 index 0000000000..061b41cb40 --- /dev/null +++ b/Examples/QuickRender/README.md @@ -0,0 +1,48 @@ +MITK Rendering with QML prototype +================================================= + +Summary +------------------ + +This mini-application "QuickRender" demonstrates how to possibly build a Qt5 QML based +application that integrates MITK render windows. + +The `QuickRender` application is located in `Examples/QuickRender` + - it provides no "File/Open" dialog + - should be called with a file loadable by MITK, e.g. a 3D ![NRRD file](http://mitk.org/git/?p=MITK-Data.git;a=blob_plain;f=Pic3D.nrrd;hb=HEAD) + +`./QuickRender ~/NRRD-testimages/nrrd3dblock.nrrd` + +![Screenshot](http://maleike.github.io/MITK/quickrender.png) + +Interaction: + - mouse clicks place the cross-hair + - mouse scroll wheel moves to neighboring slice + - holding the right mouse button and moving up/down changes the zoom level + - holding the middle mouse button and mosing pans the scene (only when zoomed in) + +Code Changes +------------------ + +A new module QmlMitk provides + - class `QmlMitkRenderWindowItem`: provides functionality like `QmitkRenderWindowm` based on `QVTKQuickItem` (from ![OpenView](https://github.com/Kitware/openview)) + - class `QmlMitkFourRenderWindowWidget`: simplified replacement for `QmitkStdMultiWidget`, a minimal combination of four `QmlMitkFourRenderWindowWidget`s + - a Qt 5, QtQuick dependency + +Build Instructions +------------------ + + - build Qt 5.1 + - place the Qt 5.1 qmake application in your environment `PATH` + - build MITK superbuild with + - `MITK_BUILD_EXAMPLES` variable switched to `ON` + - advanced option `MITK_USE_CTK` switched to `OFF` + - `MITK_USE_BLUEBERRY` and `MITK_USE_QT` switched to `OFF` (MITK_USE_QT finds Qt 4) + +Open Issues +------------------ + + - Build system integration of Qt 5 dependency + - Build system integration of OpenView package + - cleaner, fuller interfaces for the two new widgets + - real solution for QmlMitkBigRenderLock diff --git a/Examples/QuickRender/main.cpp b/Examples/QuickRender/main.cpp new file mode 100644 index 0000000000..1b418e2fa4 --- /dev/null +++ b/Examples/QuickRender/main.cpp @@ -0,0 +1,113 @@ + +#include "QmlMitkFourRenderWindowWidget.h" + +#include +#include + +#include "mitkStandaloneDataStorage.h" +#include "mitkDataNodeFactory.h" +#include "mitkGlobalInteraction.h" + +#include "QmlMitkBigRenderLock.h" + +mitk::DataStorage::Pointer FillDataStorage(int argc, char **argv) +{ + if (argc < 2) + { + fprintf(stderr, "Usage: %s [filename1] [filename2] ...\n\n", ""); + return NULL; + } + + // Create a DataStorage + mitk::DataStorage::Pointer storage = mitk::StandaloneDataStorage::New().GetPointer(); + + //************************************************************************* + // Part II: Create some data by reading files + //************************************************************************* + int i; + for (i = 1; i < argc; ++i) + { + // For testing + if (strcmp(argv[i], "-testing") == 0) + continue; + + // Create a DataNodeFactory to read a data format supported + // by the DataNodeFactory (many image formats, surface formats, etc.) + mitk::DataNodeFactory::Pointer nodeReader = mitk::DataNodeFactory::New(); + const char * filename = argv[i]; + try + { + nodeReader->SetFileName(filename); + nodeReader->Update(); + + // Since the DataNodeFactory directly creates a node, + // use the datastorage to add the read node + mitk::DataNode::Pointer node = nodeReader->GetOutput(); + storage->Add(node); + + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + if (image.IsNotNull()) + { + // Set the property "volumerendering" to the Boolean value "true" + node->SetProperty("volumerendering", mitk::BoolProperty::New(false)); + node->SetProperty("name", mitk::StringProperty::New("testimage")); + node->SetProperty("layer", mitk::IntProperty::New(1)); + } + } catch (...) + { + fprintf(stderr, "Could not open file %s \n\n", filename); + return 0; + } + } + + return storage; +} + +#include "QmlMitkRenderingManagerFactory.h" +void MitkStaticInitialization() +{ + // TODO THIS IS BAD! Move to module activator + static QmlMitkRenderingManagerFactory sanglier; + + mitk::GlobalInteraction::GetInstance()->Initialize("global"); // unbelievable.. still necessary.. +} + +void SetupRenderWindowItems( QQuickItem* container, mitk::DataStorage::Pointer dataStorage ) +{ + QmlMitkFourRenderWindowWidget* mitkMultiWidget = container->findChild("mitkMultiWidget"); + if (mitkMultiWidget) + { + mitkMultiWidget->SetDataStorage( dataStorage ); + } + else + { + MITK_ERROR << "No QmlMitkFourRenderWindowWidget item found during QuickRender application initialization. Uh oh.."; + exit(EXIT_FAILURE); + } +} + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + MitkStaticInitialization(); + mitk::DataStorage::Pointer dataStorage = FillDataStorage(argc,argv); + + // TODO: where to put this? Module activator?? There must be a more Qt-style place.. + qmlRegisterType("QmlMitk", 1, 0, "QmlMitkRenderWindowItem"); + qmlRegisterType("QmlMitk", 1, 0, "QmlMitkFourRenderWindowWidget"); + QQuickView view; + + view.setSource(QUrl("qrc:///MITK/Examples/QuickRender/QuickRender.qml")); + view.setResizeMode( QQuickView::SizeRootObjectToView ); + + + QQuickItem* root = view.rootObject(); + SetupRenderWindowItems( root, dataStorage ); + + view.show(); + + QmlMitkBigRenderLock giantRenderLock; + app.installEventFilter(&giantRenderLock); + return app.exec(); +} diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index a3b8cc9ad2..b4a949e20e 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -1,64 +1,66 @@ set(LIBPOSTFIX "Ext") # Modules must be listed according to their dependencies set(module_dirs SceneSerializationBase PlanarFigure ImageExtraction ImageStatistics LegacyAdaptors IpPicSupport MitkExt SceneSerialization GraphAlgorithms ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation + OpenView + QmlMitk Qmitk QmitkExt SegmentationUI DiffusionImaging GPGPU IGT CameraCalibration IGTUI RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport Overlays InputDevices ToFHardware ToFProcessing ToFUI US ClippingTools USUI DicomUI Simulation Remeshing Python ) set(MITK_DEFAULT_SUBPROJECTS MITK-Modules) foreach(module_dir ${module_dirs}) add_subdirectory(${module_dir}) endforeach() if(MITK_PRIVATE_MODULES) file(GLOB all_subdirs RELATIVE ${MITK_PRIVATE_MODULES} ${MITK_PRIVATE_MODULES}/*) foreach(subdir ${all_subdirs}) string(FIND ${subdir} "." _result) if(_result EQUAL -1) if(EXISTS ${MITK_PRIVATE_MODULES}/${subdir}/CMakeLists.txt) message(STATUS "Found private module ${subdir}") add_subdirectory(${MITK_PRIVATE_MODULES}/${subdir} private_modules/${subdir}) endif() endif() endforeach() endif(MITK_PRIVATE_MODULES) diff --git a/Modules/OpenView/CMakeLists.txt b/Modules/OpenView/CMakeLists.txt new file mode 100644 index 0000000000..1ddd15f22d --- /dev/null +++ b/Modules/OpenView/CMakeLists.txt @@ -0,0 +1,4 @@ +MITK_CREATE_MODULE(OpenView + PACKAGE_DEPENDS Qt5 VTK OpenGL + EXPORT_DEFINE OVCORE_EXPORT) + diff --git a/Modules/OpenView/QVTKInteractor.cxx b/Modules/OpenView/QVTKInteractor.cxx new file mode 100644 index 0000000000..9b1a89ad78 --- /dev/null +++ b/Modules/OpenView/QVTKInteractor.cxx @@ -0,0 +1,265 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: QVTKWidget.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +#ifdef _MSC_VER +// Disable warnings that Qt headers give. +#pragma warning(disable:4127) +#pragma warning(disable:4512) +#endif + +#include "QVTKInteractor.h" +#include "QVTKInteractorInternal.h" + +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) +# include "vtkTDxWinDevice.h" +#endif + +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) +# include "vtkTDxMacDevice.h" +#endif + +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) +# include "vtkTDxUnixDevice.h" +#endif + +#include +#include +#include +#include + +#include "vtkObjectFactory.h" +#include "vtkCommand.h" +#include "vtkRenderWindow.h" + +QVTKInteractorInternal::QVTKInteractorInternal(QVTKInteractor* p) + : Parent(p) +{ + this->SignalMapper = new QSignalMapper(this); + QObject::connect(this->SignalMapper, SIGNAL(mapped(int)), this, SLOT(TimerEvent(int)) ); +} + +QVTKInteractorInternal::~QVTKInteractorInternal() +{ +} + +void QVTKInteractorInternal::TimerEvent(int id) +{ + Parent->TimerEvent(id); +} + +/*! allocation method for Qt/VTK interactor + */ +vtkStandardNewMacro(QVTKInteractor); + +/*! constructor for Qt/VTK interactor + */ +QVTKInteractor::QVTKInteractor() +{ + this->Internal = new QVTKInteractorInternal(this); + +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + this->Device=vtkTDxWinDevice::New(); +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + this->Device=vtkTDxMacDevice::New(); +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + this->Device=0; +#endif +} + +void QVTKInteractor::Initialize() +{ +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + if(this->UseTDx) + { + // this is QWidget::winId(); + HWND hWnd=static_cast(this->GetRenderWindow()->GetGenericWindowId()); + if(!this->Device->GetInitialized()) + { + this->Device->SetInteractor(this); + this->Device->SetWindowHandle(hWnd); + this->Device->Initialize(); + } + } +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + if(this->UseTDx) + { + if(!this->Device->GetInitialized()) + { + this->Device->SetInteractor(this); + // Do not initialize the device here. + } + } +#endif + this->Initialized = 1; + this->Enable(); +} + +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) +// ---------------------------------------------------------------------------- +vtkTDxUnixDevice *QVTKInteractor::GetDevice() +{ + return this->Device; +} + +// ---------------------------------------------------------------------------- +void QVTKInteractor::SetDevice(vtkTDxDevice *device) +{ + if(this->Device!=device) + { + this->Device=static_cast(device); + } +} +#endif + + +/*! start method for interactor + */ +void QVTKInteractor::Start() +{ + vtkErrorMacro(<<"QVTKInteractor cannot control the event loop."); +} + +/*! terminate the application + */ +void QVTKInteractor::TerminateApp() +{ + // we are in a GUI so let's terminate the GUI the normal way + //qApp->exit(); +} + +// ---------------------------------------------------------------------------- +void QVTKInteractor::StartListening() +{ +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + if(this->Device->GetInitialized() && !this->Device->GetIsListening()) + { + this->Device->StartListening(); + } +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + if(this->UseTDx && !this->Device->GetInitialized()) + { + this->Device->Initialize(); + } +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + if(this->UseTDx && this->Device!=0) + { + this->Device->SetInteractor(this); + } +#endif +} + +// ---------------------------------------------------------------------------- +void QVTKInteractor::StopListening() +{ +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + if(this->Device->GetInitialized() && this->Device->GetIsListening()) + { + this->Device->StopListening(); + } +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + if(this->UseTDx && this->Device->GetInitialized()) + { + this->Device->Close(); + } +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + if(this->UseTDx && this->Device!=0) + { + // this assumes that a outfocus event is emitted prior + // a infocus event on another widget. + this->Device->SetInteractor(0); + } +#endif +} + + +/*! handle timer event + */ +void QVTKInteractor::TimerEvent(int timerId) +{ + if ( !this->GetEnabled() ) + { + return; + } + this->InvokeEvent(vtkCommand::TimerEvent, (void*)&timerId); + + if(this->IsOneShotTimer(timerId)) + { + this->DestroyTimer(timerId); // 'cause our Qt timers are always repeating + } +} + +/*! constructor + */ +QVTKInteractor::~QVTKInteractor() +{ + delete this->Internal; +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + this->Device->Delete(); +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + this->Device->Delete(); +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + this->Device=0; +#endif +} + +/*! create Qt timer with an interval of 10 msec. + */ +int QVTKInteractor::InternalCreateTimer(int timerId, int vtkNotUsed(timerType), unsigned long duration) +{ + QTimer* timer = new QTimer(this->Internal); + timer->start(duration); + this->Internal->SignalMapper->setMapping(timer, timerId); + QObject::connect(timer, SIGNAL(timeout()), this->Internal->SignalMapper, SLOT(map())); + int platformTimerId = timer->timerId(); + this->Internal->Timers.insert(QVTKInteractorInternal::TimerMap::value_type(platformTimerId, timer)); + return platformTimerId; +} + +/*! destroy timer + */ +int QVTKInteractor::InternalDestroyTimer(int platformTimerId) +{ + QVTKInteractorInternal::TimerMap::iterator iter = this->Internal->Timers.find(platformTimerId); + if(iter != this->Internal->Timers.end()) + { + iter->second->stop(); + iter->second->deleteLater(); + this->Internal->Timers.erase(iter); + return 1; + } + return 0; +} diff --git a/Modules/OpenView/QVTKInteractor.h b/Modules/OpenView/QVTKInteractor.h new file mode 100644 index 0000000000..9a5b52c440 --- /dev/null +++ b/Modules/OpenView/QVTKInteractor.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: QVTKInteractor.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +// .NAME QVTKInteractor - Handle Qt events. +// .SECTION Description +// QVTKInteractor handles relaying Qt events to VTK. + +#ifndef Q_VTK_INTERACTOR_H +#define Q_VTK_INTERACTOR_H + +#include +#include +#include + +#include "vtkTDxConfigure.h" // defines VTK_USE_TDX +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) +class vtkTDxWinDevice; +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) +class vtkTDxMacDevice; +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) +class vtkTDxDevice; +class vtkTDxUnixDevice; +#endif + +#include "OpenViewExports.h" + +class QVTKInteractorInternal; + +// .NAME QVTKInteractor - An interactor for the QVTKWidget. +// .SECTION Description +// QVTKInteractor is an interactor for a QVTKWiget. + +class OVCORE_EXPORT QVTKInteractor : public vtkRenderWindowInteractor +{ +public: + static QVTKInteractor* New(); + vtkTypeMacro(QVTKInteractor,vtkRenderWindowInteractor); + + // Description: + // Enum for additional event types supported. + // These events can be picked up by command observers on the interactor + enum vtkCustomEvents + { + ContextMenuEvent = vtkCommand::UserEvent + 100, + DragEnterEvent, + DragMoveEvent, + DragLeaveEvent, + DropEvent + }; + + + // Description: + // Overloaded terminiate app, which does nothing in Qt. + // Use qApp->exit() instead. + virtual void TerminateApp(); + + // Description: + // Overloaded start method does nothing. + // Use qApp->exec() instead. + virtual void Start(); + virtual void Initialize(); + + // Description: + // Start listening events on 3DConnexion device. + virtual void StartListening(); + + // Description: + // Stop listening events on 3DConnexion device. + virtual void StopListening(); + + // timer event slot + virtual void TimerEvent(int timerId); + +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + virtual vtkTDxUnixDevice *GetDevice(); + virtual void SetDevice(vtkTDxDevice *device); +#endif + +protected: + // constructor + QVTKInteractor(); + // destructor + ~QVTKInteractor(); + + // create a Qt Timer + virtual int InternalCreateTimer(int timerId, int timerType, unsigned long duration); + // destroy a Qt Timer + virtual int InternalDestroyTimer(int platformTimerId); +#if defined(VTK_USE_TDX) && defined(Q_WS_WIN) + vtkTDxWinDevice *Device; +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_MAC) + vtkTDxMacDevice *Device; +#endif +#if defined(VTK_USE_TDX) && defined(Q_WS_X11) + vtkTDxUnixDevice *Device; +#endif + +private: + + QVTKInteractorInternal* Internal; + + // unimplemented copy + QVTKInteractor(const QVTKInteractor&); + // unimplemented operator= + void operator=(const QVTKInteractor&); + +}; + +#endif diff --git a/Modules/OpenView/QVTKInteractorAdapter.cxx b/Modules/OpenView/QVTKInteractorAdapter.cxx new file mode 100644 index 0000000000..4fd856e0a8 --- /dev/null +++ b/Modules/OpenView/QVTKInteractorAdapter.cxx @@ -0,0 +1,455 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: QVTKInteractorAdapter.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +#ifdef _MSC_VER +// Disable warnings that Qt headers give. +#pragma warning(disable:4127) +#pragma warning(disable:4512) +#endif + +#include "QVTKInteractorAdapter.h" +#include "QVTKInteractor.h" + +#include +#include +#include +#include + +#include "vtkCommand.h" + + +// function to get VTK keysyms from ascii characters +static const char* ascii_to_key_sym(int); +// function to get VTK keysyms from Qt keys +static const char* qt_key_to_key_sym(Qt::Key, Qt::KeyboardModifiers modifiers); + +QVTKInteractorAdapter::QVTKInteractorAdapter(QObject* parentObject) + : QObject(parentObject) +{ +} + +QVTKInteractorAdapter::~QVTKInteractorAdapter() +{ +} + +bool QVTKInteractorAdapter::ProcessEvent(QEvent* e, vtkRenderWindowInteractor* iren) +{ + if(iren == NULL || e == NULL) + return false; + + const QEvent::Type t = e->type(); + + if(t == QEvent::Resize) + { + QResizeEvent* e2 = static_cast(e); + QSize size = e2->size(); + iren->SetSize(size.width(), size.height()); + return true; + } + + if(t == QEvent::FocusIn) + { + // For 3DConnexion devices: + QVTKInteractor* qiren = QVTKInteractor::SafeDownCast(iren); + if(qiren) + { + qiren->StartListening(); + } + return true; + } + + if(t == QEvent::FocusOut) + { + // For 3DConnexion devices: + QVTKInteractor* qiren = QVTKInteractor::SafeDownCast(iren); + if(qiren) + { + qiren->StopListening(); + } + return true; + } + + // the following events only happen if the interactor is enabled + if(!iren->GetEnabled()) + return false; + + if(t == QEvent::MouseButtonPress || + t == QEvent::MouseButtonRelease || + t == QEvent::MouseButtonDblClick || + t == QEvent::MouseMove) + { + QMouseEvent* e2 = static_cast(e); + + // give interactor the event information + iren->SetEventInformationFlipY(e2->x(), e2->y(), + (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, + (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0, + 0, + e2->type() == QEvent::MouseButtonDblClick ? 1 : 0); + + if(t == QEvent::MouseMove) + { + iren->InvokeEvent(vtkCommand::MouseMoveEvent, e2); + } + else if(t == QEvent::MouseButtonPress || t == QEvent::MouseButtonDblClick) + { + switch(e2->button()) + { + case Qt::LeftButton: + iren->InvokeEvent(vtkCommand::LeftButtonPressEvent, e2); + break; + + case Qt::MidButton: + iren->InvokeEvent(vtkCommand::MiddleButtonPressEvent, e2); + break; + + case Qt::RightButton: + iren->InvokeEvent(vtkCommand::RightButtonPressEvent, e2); + break; + + default: + break; + } + } + else if(t == QEvent::MouseButtonRelease) + { + switch(e2->button()) + { + case Qt::LeftButton: + iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, e2); + break; + + case Qt::MidButton: + iren->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, e2); + break; + + case Qt::RightButton: + iren->InvokeEvent(vtkCommand::RightButtonReleaseEvent, e2); + break; + + default: + break; + } + } + return true; + } + + if(t == QEvent::Enter) + { + iren->InvokeEvent(vtkCommand::EnterEvent, e); + return true; + } + + if(t == QEvent::Leave) + { + iren->InvokeEvent(vtkCommand::LeaveEvent, e); + return true; + } + + if(t == QEvent::KeyPress || t == QEvent::KeyRelease) + { + QKeyEvent* e2 = static_cast(e); + + // get key and keysym information + int ascii_key = e2->text().length() ? e2->text().unicode()->toLatin1() : 0; + const char* keysym = ascii_to_key_sym(ascii_key); + if(!keysym || + e2->modifiers() == Qt::KeypadModifier) + { + // get virtual keys + keysym = qt_key_to_key_sym(static_cast(e2->key()), + e2->modifiers()); + } + + if(!keysym) + { + keysym = "None"; + } + + // give interactor event information + iren->SetKeyEventInformation( + (e2->modifiers() & Qt::ControlModifier), + (e2->modifiers() & Qt::ShiftModifier), + ascii_key, e2->count(), keysym); + + if(t == QEvent::KeyPress) + { + // invoke vtk event + iren->InvokeEvent(vtkCommand::KeyPressEvent, e2); + + // invoke char event only for ascii characters + if(ascii_key) + { + iren->InvokeEvent(vtkCommand::CharEvent, e2); + } + } + else + { + iren->InvokeEvent(vtkCommand::KeyReleaseEvent, e2); + } + return true; + } + + if(t == QEvent::Wheel) + { + QWheelEvent* e2 = static_cast(e); + + iren->SetEventInformationFlipY(e2->x(), e2->y(), + (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, + (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0); + + // invoke vtk event + // if delta is positive, it is a forward wheel event + if(e2->delta() > 0) + { + iren->InvokeEvent(vtkCommand::MouseWheelForwardEvent, e2); + } + else + { + iren->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, e2); + } + return true; + } + + if(t == QEvent::ContextMenu) + { + QContextMenuEvent* e2 = static_cast(e); + + // give interactor the event information + iren->SetEventInformationFlipY(e2->x(), e2->y(), + (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, + (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKInteractor::ContextMenuEvent, e2); + + return true; + } + + if(t == QEvent::DragEnter) + { + QDragEnterEvent* e2 = static_cast(e); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKInteractor::DragEnterEvent, e2); + + return true; + } + + if(t == QEvent::DragLeave) + { + QDragLeaveEvent* e2 = static_cast(e); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKInteractor::DragLeaveEvent, e2); + + return true; + } + + if(t == QEvent::DragMove) + { + QDragMoveEvent* e2 = static_cast(e); + + // give interactor the event information + iren->SetEventInformationFlipY(e2->pos().x(), e2->pos().y()); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKInteractor::DragMoveEvent, e2); + return true; + } + + if(t == QEvent::Drop) + { + QDropEvent* e2 = static_cast(e); + + // give interactor the event information + iren->SetEventInformationFlipY(e2->pos().x(), e2->pos().y()); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKInteractor::DropEvent, e2); + return true; + } + + return false; +} + +// ***** keysym stuff below ***** + +static const char *AsciiToKeySymTable[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, "Tab", 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", + "parenleft", "parenright", "asterisk", "plus", + "comma", "minus", "period", "slash", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "colon", "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", + "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +const char* ascii_to_key_sym(int i) +{ + if(i >= 0) + { + return AsciiToKeySymTable[i]; + } + return 0; +} + +#define QVTK_HANDLE(x,y) \ + case x : \ + ret = y; \ + break; + +#define QVTK_HANDLE_KEYPAD(x, y, z) \ + case x : \ + ret = (modifiers & Qt::KeypadModifier) ? (y) : (z); \ + break; + +const char* qt_key_to_key_sym(Qt::Key i, Qt::KeyboardModifiers modifiers) +{ + const char* ret = 0; + switch(i) + { + // Cancel + QVTK_HANDLE(Qt::Key_Backspace, "BackSpace") + QVTK_HANDLE(Qt::Key_Tab, "Tab") + QVTK_HANDLE(Qt::Key_Backtab, "Tab") + QVTK_HANDLE(Qt::Key_Clear, "Clear") + QVTK_HANDLE(Qt::Key_Return, "Return") + QVTK_HANDLE(Qt::Key_Enter, "Return") + QVTK_HANDLE(Qt::Key_Shift, "Shift_L") + QVTK_HANDLE(Qt::Key_Control, "Control_L") + QVTK_HANDLE(Qt::Key_Alt, "Alt_L") + QVTK_HANDLE(Qt::Key_Pause, "Pause") + QVTK_HANDLE(Qt::Key_CapsLock, "Caps_Lock") + QVTK_HANDLE(Qt::Key_Escape, "Escape") + QVTK_HANDLE(Qt::Key_Space, "space") + QVTK_HANDLE(Qt::Key_PageUp, "Prior") + QVTK_HANDLE(Qt::Key_PageDown, "Next") + QVTK_HANDLE(Qt::Key_End, "End") + QVTK_HANDLE(Qt::Key_Home, "Home") + QVTK_HANDLE(Qt::Key_Left, "Left") + QVTK_HANDLE(Qt::Key_Up, "Up") + QVTK_HANDLE(Qt::Key_Right, "Right") + QVTK_HANDLE(Qt::Key_Down, "Down") + QVTK_HANDLE(Qt::Key_Select, "Select") + QVTK_HANDLE(Qt::Key_Execute, "Execute") + QVTK_HANDLE(Qt::Key_SysReq, "Snapshot") + QVTK_HANDLE(Qt::Key_Insert, "Insert") + QVTK_HANDLE(Qt::Key_Delete, "Delete") + QVTK_HANDLE(Qt::Key_Help, "Help") + QVTK_HANDLE_KEYPAD(Qt::Key_0, "KP_0", "0") + QVTK_HANDLE_KEYPAD(Qt::Key_1, "KP_1", "1") + QVTK_HANDLE_KEYPAD(Qt::Key_2, "KP_2", "2") + QVTK_HANDLE_KEYPAD(Qt::Key_3, "KP_3", "3") + QVTK_HANDLE_KEYPAD(Qt::Key_4, "KP_4", "4") + QVTK_HANDLE_KEYPAD(Qt::Key_5, "KP_5", "5") + QVTK_HANDLE_KEYPAD(Qt::Key_6, "KP_6", "6") + QVTK_HANDLE_KEYPAD(Qt::Key_7, "KP_7", "7") + QVTK_HANDLE_KEYPAD(Qt::Key_8, "KP_8", "8") + QVTK_HANDLE_KEYPAD(Qt::Key_9, "KP_9", "9") + QVTK_HANDLE(Qt::Key_A, "a") + QVTK_HANDLE(Qt::Key_B, "b") + QVTK_HANDLE(Qt::Key_C, "c") + QVTK_HANDLE(Qt::Key_D, "d") + QVTK_HANDLE(Qt::Key_E, "e") + QVTK_HANDLE(Qt::Key_F, "f") + QVTK_HANDLE(Qt::Key_G, "g") + QVTK_HANDLE(Qt::Key_H, "h") + QVTK_HANDLE(Qt::Key_I, "i") + QVTK_HANDLE(Qt::Key_J, "h") + QVTK_HANDLE(Qt::Key_K, "k") + QVTK_HANDLE(Qt::Key_L, "l") + QVTK_HANDLE(Qt::Key_M, "m") + QVTK_HANDLE(Qt::Key_N, "n") + QVTK_HANDLE(Qt::Key_O, "o") + QVTK_HANDLE(Qt::Key_P, "p") + QVTK_HANDLE(Qt::Key_Q, "q") + QVTK_HANDLE(Qt::Key_R, "r") + QVTK_HANDLE(Qt::Key_S, "s") + QVTK_HANDLE(Qt::Key_T, "t") + QVTK_HANDLE(Qt::Key_U, "u") + QVTK_HANDLE(Qt::Key_V, "v") + QVTK_HANDLE(Qt::Key_W, "w") + QVTK_HANDLE(Qt::Key_X, "x") + QVTK_HANDLE(Qt::Key_Y, "y") + QVTK_HANDLE(Qt::Key_Z, "z") + QVTK_HANDLE(Qt::Key_Asterisk, "asterisk") + QVTK_HANDLE(Qt::Key_Plus, "plus") + QVTK_HANDLE(Qt::Key_Bar, "bar") + QVTK_HANDLE(Qt::Key_Minus, "minus") + QVTK_HANDLE(Qt::Key_Period, "period") + QVTK_HANDLE(Qt::Key_Slash, "slash") + QVTK_HANDLE(Qt::Key_F1, "F1") + QVTK_HANDLE(Qt::Key_F2, "F2") + QVTK_HANDLE(Qt::Key_F3, "F3") + QVTK_HANDLE(Qt::Key_F4, "F4") + QVTK_HANDLE(Qt::Key_F5, "F5") + QVTK_HANDLE(Qt::Key_F6, "F6") + QVTK_HANDLE(Qt::Key_F7, "F7") + QVTK_HANDLE(Qt::Key_F8, "F8") + QVTK_HANDLE(Qt::Key_F9, "F9") + QVTK_HANDLE(Qt::Key_F10, "F10") + QVTK_HANDLE(Qt::Key_F11, "F11") + QVTK_HANDLE(Qt::Key_F12, "F12") + QVTK_HANDLE(Qt::Key_F13, "F13") + QVTK_HANDLE(Qt::Key_F14, "F14") + QVTK_HANDLE(Qt::Key_F15, "F15") + QVTK_HANDLE(Qt::Key_F16, "F16") + QVTK_HANDLE(Qt::Key_F17, "F17") + QVTK_HANDLE(Qt::Key_F18, "F18") + QVTK_HANDLE(Qt::Key_F19, "F19") + QVTK_HANDLE(Qt::Key_F20, "F20") + QVTK_HANDLE(Qt::Key_F21, "F21") + QVTK_HANDLE(Qt::Key_F22, "F22") + QVTK_HANDLE(Qt::Key_F23, "F23") + QVTK_HANDLE(Qt::Key_F24, "F24") + QVTK_HANDLE(Qt::Key_NumLock, "Num_Lock") + QVTK_HANDLE(Qt::Key_ScrollLock, "Scroll_Lock") + + default: + break; + } + return ret; +} diff --git a/Modules/OpenView/QVTKInteractorAdapter.h b/Modules/OpenView/QVTKInteractorAdapter.h new file mode 100644 index 0000000000..bed52745f4 --- /dev/null +++ b/Modules/OpenView/QVTKInteractorAdapter.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: QVTKInteractorAdapter.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +// .NAME QVTKInteractorAdapter - Handle Qt events. +// .SECTION Description +// QVTKInteractor handles relaying Qt events to VTK. + +#ifndef Q_VTK_INTERACTOR_ADAPTER_H +#define Q_VTK_INTERACTOR_ADAPTER_H + +#include + +#include "OpenViewExports.h" + +class vtkRenderWindowInteractor; +class QEvent; + +// .NAME QVTKInteractorAdapter - A QEvent translator. +// .SECTION Description +// QVTKInteractorAdapter translates QEvents and send them to a +// vtkRenderWindowInteractor. +class OVCORE_EXPORT QVTKInteractorAdapter : public QObject +{ + Q_OBJECT +public: + // Description: + // Constructor: takes QObject parent + QVTKInteractorAdapter(QObject* parent); + + // Description: + // Destructor + ~QVTKInteractorAdapter(); + + // Description: + // Process a QEvent and send it to the interactor + // returns whether the event was recognized and processed + bool ProcessEvent(QEvent* e, vtkRenderWindowInteractor* iren); +}; + +#endif diff --git a/Modules/OpenView/QVTKInteractorInternal.h b/Modules/OpenView/QVTKInteractorInternal.h new file mode 100644 index 0000000000..82b83cb7bd --- /dev/null +++ b/Modules/OpenView/QVTKInteractorInternal.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: QVTKInteractor.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +#ifndef Q_VTK_INTERACTOR_INTERNAL_H +#define Q_VTK_INTERACTOR_INTERNAL_H + +#include + +#include +class QVTKInteractor; +class QSignalMapper; +class QTimer; + +// internal class, do not use +class QVTKInteractorInternal : public QObject +{ + Q_OBJECT +public: + QVTKInteractorInternal(QVTKInteractor* p); + ~QVTKInteractorInternal(); +public Q_SLOTS: + void TimerEvent(int id); +public: + QSignalMapper* SignalMapper; + typedef std::map TimerMap; + TimerMap Timers; + QVTKInteractor* Parent; +}; + + +#endif diff --git a/Modules/OpenView/QVTKQuickItem.cxx b/Modules/OpenView/QVTKQuickItem.cxx new file mode 100644 index 0000000000..9f05230509 --- /dev/null +++ b/Modules/OpenView/QVTKQuickItem.cxx @@ -0,0 +1,376 @@ +/*======================================================================== + OpenView -- http://openview.kitware.com + + Copyright 2012 Kitware, Inc. + + Licensed under the BSD license. See LICENSE file for details. + ========================================================================*/ +#include "QVTKQuickItem.h" + +#include +#include +#include +#include +#include +#include + +#include "QVTKInteractor.h" +#include "QVTKInteractorAdapter.h" +#include "vtkGenericOpenGLRenderWindow.h" +#include "vtkEventQtSlotConnect.h" +#include "vtkgl.h" +#include "vtkOpenGLExtensionManager.h" +#include "vtkRenderer.h" +#include "vtkRendererCollection.h" + +#include "vtkCubeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" + + +#include + +QVTKQuickItem::QVTKQuickItem(QQuickItem* parent) +:QQuickItem(parent) +,m_InitCalledOnce(false) +{ + setFlag(ItemHasContents); + setAcceptHoverEvents(true); + setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); + + m_interactor = vtkSmartPointer::New(); + m_interactorAdapter = new QVTKInteractorAdapter(NULL); + m_interactorAdapter->moveToThread(this->thread()); + m_interactorAdapter->setParent(this); + m_connect = vtkSmartPointer::New(); + //m_connect->Connect(m_interactor, vtkCommand::RenderEvent, this, SLOT(paint())); + vtkSmartPointer win = vtkSmartPointer::New(); + this->SetRenderWindow(win); + this->geometryChanged(QRectF(x(), y(), width(), height()), QRectF(0, 0, 100, 100)); +} + +QVTKQuickItem::~QVTKQuickItem() +{ + this->SetRenderWindow(0); +} + +void QVTKQuickItem::SetRenderWindow(vtkGenericOpenGLRenderWindow* win) +{ + if(m_win) + { + m_win->SetMapped(0); + //m_connect->Disconnect(m_win, vtkCommand::StartEvent, this, SLOT(Start())); + //m_connect->Disconnect(m_win, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent())); + //m_connect->Disconnect(m_win, vtkCommand::EndEvent, this, SLOT(End())); + //m_connect->Disconnect(m_win, vtkCommand::WindowFrameEvent, this, SLOT(Update())); + m_connect->Disconnect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*))); + m_connect->Disconnect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*))); + m_connect->Disconnect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*))); + } + + m_interactor->SetRenderWindow(win); + m_win = win; + m_interactor->Initialize(); + + if(m_win) + { + m_win->SetMapped(1); + m_win->SetDoubleBuffer(0); + m_win->SetFrontBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + m_win->SetFrontLeftBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + m_win->SetBackBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + m_win->SetBackLeftBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + + //m_connect->Connect(m_win, vtkCommand::StartEvent, this, SLOT(Start())); + //m_connect->Connect(m_win, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent())); + //m_connect->Connect(m_win, vtkCommand::EndEvent, this, SLOT(End())); + //m_connect->Connect(m_win, vtkCommand::WindowFrameEvent, this, SLOT(Update())); + // Qt::DirectConnection in order to execute callback immediately. + // This avoids an error when vtkTexture attempts to query driver features and it is unable to determine "IsCurrent" + m_connect->Connect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + m_connect->Connect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + m_connect->Connect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + } +} + +vtkGenericOpenGLRenderWindow* QVTKQuickItem::GetRenderWindow() const +{ + return m_win; +} + +QVTKInteractor* QVTKQuickItem::GetInteractor() const +{ + return m_interactor; +} + +void QVTKQuickItem::itemChange(ItemChange change, const ItemChangeData &) +{ + // The ItemSceneChange event is sent when we are first attached to a canvas. + if (change == ItemSceneChange) { + QQuickWindow *c = window(); + if (!c) + { + return; + } + + // Connect our the beforeRendering signal to our paint function. + // Since this call is executed on the rendering thread it must be + // a Qt::DirectConnection + connect(c, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + + // If we allow QML to do the clearing, they would clear what we paint + // and nothing would show. + c->setClearBeforeRendering(false); + } +} + +void QVTKQuickItem::MakeCurrent() +{ + if (!this->window()) + { + m_win->SetAbortRender(1); + cerr << "Could not make current since there is no canvas!" << endl; + return; + } + if (QThread::currentThread() != this->window()->openglContext()->thread()) + { + m_win->SetAbortRender(1); + cerr << "Could not make current since we are on the wrong thread!" << endl; + return; + } + this->window()->openglContext()->makeCurrent(this->window()); +} + +void QVTKQuickItem::Start() +{ + MakeCurrent(); + + if (!m_win->GetAbortRender()) + { + m_win->PushState(); + m_win->OpenGLInitState(); + } +} + +void QVTKQuickItem::End() +{ + if (!m_win->GetAbortRender()) + { + m_win->PopState(); + } + +} + +void QVTKQuickItem::IsCurrent(vtkObject*, unsigned long, void*, void* call_data) +{ + bool* ptr = reinterpret_cast(call_data); + *ptr = QOpenGLContext::currentContext() == this->window()->openglContext(); +} + +void QVTKQuickItem::IsDirect(vtkObject*, unsigned long, void*, void* call_data) +{ + int* ptr = reinterpret_cast(call_data); + *ptr = 1; +} + +void QVTKQuickItem::SupportsOpenGL(vtkObject*, unsigned long, void*, void* call_data) +{ + int* ptr = reinterpret_cast(call_data); + *ptr = true; + //*ptr = QGLFormat::hasOpenGL(); +} + +void QVTKQuickItem::geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry) +{ + QQuickItem::geometryChanged(newGeometry, oldGeometry); + QSize oldSize(oldGeometry.width(), oldGeometry.height()); + QSize newSize(newGeometry.width(), newGeometry.height()); + QResizeEvent e(newSize, oldSize); + if (m_interactorAdapter) + { + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e, m_interactor); + this->m_viewLock.unlock(); + } + if(m_win.GetPointer() && window()) + { + this->m_viewLock.lock(); + m_win->SetSize(window()->width(), window()->height()); + QPointF origin = mapToScene(QPointF(0, 0)); + QPointF minPt(origin.x()/window()->width(), (window()->height() - origin.y() - height())/window()->height()); + QPointF maxPt(minPt.x() + width()/window()->width(), minPt.y() + height()/window()->height()); + if (m_win->GetRenderers()->GetFirstRenderer()) + { + m_win->GetRenderers()->GetFirstRenderer()->SetViewport(minPt.x(), minPt.y(), maxPt.x(), maxPt.y()); + } + this->m_viewLock.unlock(); + update(); + } +} + +void QVTKQuickItem::keyPressEvent(QKeyEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::keyReleaseEvent(QKeyEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mousePressEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseReleaseEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseDoubleClickEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseMoveEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::wheelEvent(QWheelEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverEnterEvent(QHoverEvent* e) +{ + e->accept(); + QEvent e2(QEvent::Enter); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverLeaveEvent(QHoverEvent* e) +{ + e->accept(); + QEvent e2(QEvent::Leave); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverMoveEvent(QHoverEvent* e) +{ + e->accept(); + QMouseEvent e2(QEvent::MouseMove, e->pos(), Qt::NoButton, Qt::NoButton, e->modifiers()); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::init() +{ +} + +void QVTKQuickItem::prepareForRender() +{ +} + +void QVTKQuickItem::cleanupAfterRender() +{ +} + +QSGNode* QVTKQuickItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) +{ + QSGSimpleRectNode *n = static_cast(oldNode); + if (!n) { + n = new QSGSimpleRectNode(); + } + n->markDirty(QSGNode::DirtyForceUpdate); + return n; +} + + +void QVTKQuickItem::paint() +{ + if (!this->isVisible()) + { + return; + } + + if (!this->m_InitCalledOnce) + { + m_win->GetExtensionManager()->LoadExtension("GL_VERSION_1_4"); + m_win->GetExtensionManager()->LoadExtension("GL_VERSION_2_0"); + + init(); + + this->m_InitCalledOnce = true; + } + + this->m_viewLock.lock(); + + // Let subclasses do something each render + prepareForRender(); + + // Make sure viewport is up to date. + // This is needed because geometryChanged() is not called when parent geometry changes, so we miss when widths/heights + // of surrounding elements change. + m_win->SetSize(window()->width(), window()->height()); + QPointF origin = mapToScene(QPointF(0, 0)); + QPointF minPt(origin.x()/window()->width(), (window()->height() - origin.y() - height())/window()->height()); + QPointF maxPt(minPt.x() + width()/window()->width(), minPt.y() + height()/window()->height()); + if (m_win->GetRenderers()->GetFirstRenderer()) + { + m_win->GetRenderers()->GetFirstRenderer()->SetViewport(minPt.x(), minPt.y(), maxPt.x(), maxPt.y()); + } + + // Turn off any QML shader program + vtkgl::UseProgram(0); + + // Set blending correctly + glEnable(GL_BLEND); + vtkgl::BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + m_win->Render(); + + // Disable alpha test for QML + glDisable(GL_ALPHA_TEST); + + cleanupAfterRender(); + + this->m_viewLock.unlock(); +} diff --git a/Modules/OpenView/QVTKQuickItem.h b/Modules/OpenView/QVTKQuickItem.h new file mode 100644 index 0000000000..925209fa50 --- /dev/null +++ b/Modules/OpenView/QVTKQuickItem.h @@ -0,0 +1,108 @@ +/*======================================================================== + OpenView -- http://openview.kitware.com + + Copyright 2012 Kitware, Inc. + + Licensed under the BSD license. See LICENSE file for details. + ========================================================================*/ +#ifndef QVTKQuickItem_h +#define QVTKQuickItem_h + +#include + +#include + +#include "vtkSmartPointer.h" +#include "vtkNew.h" + +#include + +#include "OpenViewExports.h" + +class QOpenGLContext; +class QOpenGLFramebufferObject; +class QVTKInteractorAdapter; +class QVTKInteractor; +class vtkEventQtSlotConnect; +class vtkGenericOpenGLRenderWindow; +class vtkObject; +class vtkContextView; + +class OVCORE_EXPORT QVTKQuickItem : public QQuickItem +{ + Q_OBJECT +public: + QVTKQuickItem(QQuickItem* parent = 0); + + // Description: + // destructor + ~QVTKQuickItem(); + + void itemChange(ItemChange change, const ItemChangeData &); + + // Description: + // set the render window to use with this item + void SetRenderWindow(vtkGenericOpenGLRenderWindow* win); + + // Description: + // get the render window used with this item + vtkGenericOpenGLRenderWindow* GetRenderWindow() const; + + // Description: + // get the render window interactor used with this item + // this item enforces its own interactor + QVTKInteractor* GetInteractor() const; + +public slots: + virtual void paint(); + +protected slots: + // slot to make this vtk render window current + virtual void MakeCurrent(); + // slot called when vtk render window starts to draw + virtual void Start(); + // slot called when vtk render window is done drawing + virtual void End(); + // slot called when vtk wants to know if the context is current + virtual void IsCurrent(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data); + // slot called when vtk wants to know if a window is direct + virtual void IsDirect(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data); + // slot called when vtk wants to know if a window supports OpenGL + virtual void SupportsOpenGL(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data); + +protected: + + virtual void init(); + virtual void prepareForRender(); + virtual void cleanupAfterRender(); + + // handle item key events + virtual void keyPressEvent(QKeyEvent* e); + virtual void keyReleaseEvent(QKeyEvent* e); + + // handle item mouse events + virtual void mousePressEvent(QMouseEvent* e); + virtual void mouseReleaseEvent(QMouseEvent* e); + virtual void mouseDoubleClickEvent(QMouseEvent* e); + virtual void mouseMoveEvent(QMouseEvent* e); + virtual void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry); + virtual void wheelEvent(QWheelEvent* e); + virtual void hoverEnterEvent(QHoverEvent* e); + virtual void hoverLeaveEvent(QHoverEvent* e); + virtual void hoverMoveEvent(QHoverEvent* e); + + virtual QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData); + + QMutex m_viewLock; + +private: + QOpenGLContext* m_context; + vtkSmartPointer m_win; + vtkSmartPointer m_interactor; + QVTKInteractorAdapter* m_interactorAdapter; + vtkSmartPointer m_connect; + + bool m_InitCalledOnce; +}; + +#endif diff --git a/Modules/OpenView/files.cmake b/Modules/OpenView/files.cmake new file mode 100644 index 0000000000..fe3d5ed297 --- /dev/null +++ b/Modules/OpenView/files.cmake @@ -0,0 +1,26 @@ +set(CPP_FILES + vtkEventQtSlotConnect.cxx + QVTKInteractor.cxx + QVTKInteractorAdapter.cxx + QVTKQuickItem.cxx + vtkQtConnection.cxx +) + +set(MOC_H_FILES + QVTKInteractorAdapter.h + QVTKInteractorInternal.h + QVTKQuickItem.h + vtkQtConnection.h +) + +# THIS is normally done by MITK_CREATE_MODULE. +# BUT we do not use the MITK definition of a "Qt module" +# because we need Qt 5 instead of Qt 4 (the MITK default) +qt5_wrap_cpp(moc_SRC ${MOC_H_FILES}) +set(CPP_FILES ${CPP_FILES} ${moc_SRC}) + +set(UI_FILES +) + +set(QRC_FILES +) diff --git a/Modules/OpenView/original.CMakeLists.txt b/Modules/OpenView/original.CMakeLists.txt new file mode 100644 index 0000000000..8879f93fe7 --- /dev/null +++ b/Modules/OpenView/original.CMakeLists.txt @@ -0,0 +1,48 @@ +qt5_wrap_cpp( ovCore_moc_files + QVTKInteractorAdapter.h + QVTKInteractorInternal.h + QVTKQuickItem.h + vtkQtConnection.h ) + +set( ovCore_srcs + vtkEventQtSlotConnect.cxx + QVTKInteractor.cxx + QVTKInteractorAdapter.cxx + QVTKQuickItem.cxx + vtkQtConnection.cxx + ${ovCore_moc_files} ) + +set( ovCore_libs + vtkRenderingFreeTypeOpenGL + vtkRenderingVolumeOpenGL + vtkInteractionStyle + ${Qt5Widgets_LIBRARIES} + ${Qt5Quick_LIBRARIES} ) + +add_library(ovCore SHARED ${ovCore_srcs}) +target_link_libraries(ovCore ${ovCore_libs}) + +# Generate export header. +generate_export_header("ovCore" EXPORT_FILE_NAME "ovCoreModule.h") + +if(APPLE) + install(TARGETS ovCore LIBRARY DESTINATION "OpenView.app/Contents/Libraries") + install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -id @executable_path/../Libraries/libovCore.dylib ${CMAKE_INSTALL_PREFIX}/OpenView.app/Contents/Libraries/libovCore.dylib)") + + # An odd requirement: since CMake decides to do some install_name_tool + # stuff automatically, it already changed the full path of libovCore.dylib + # to simply the library file with no path. So here we need to change + # that change to instead be relative to @executable_path. If CMake did + # "help" us like that, we would expect to use the following line: + # + # set(install_name_changes "${install_name_changes} -change ${CMAKE_CURRENT_BINARY_DIR}/libovCore.dylib @executable_path/../Libraries/libovCore.dylib" PARENT_SCOPE) + set(install_name_changes "${install_name_changes} -change libovCore.dylib @executable_path/../Libraries/libovCore.dylib" PARENT_SCOPE) + + list(APPEND libs_and_execs "${CMAKE_INSTALL_PREFIX}/OpenView.app/Contents/Libraries/libovCore.dylib") + set(libs_and_execs ${libs_and_execs} PARENT_SCOPE) +else() + install(TARGETS ovCore + RUNTIME DESTINATION "bin" + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib") +endif() diff --git a/Modules/OpenView/vtkEventQtSlotConnect.cxx b/Modules/OpenView/vtkEventQtSlotConnect.cxx new file mode 100644 index 0000000000..411f701cd5 --- /dev/null +++ b/Modules/OpenView/vtkEventQtSlotConnect.cxx @@ -0,0 +1,149 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "vtkEventQtSlotConnect.h" +#include "vtkObjectFactory.h" +#include "vtkCallbackCommand.h" +#include "vtkQtConnection.h" + +#include + +#include + +// hold all the connections +class vtkQtConnections : public std::vector< vtkQtConnection* > {}; + +vtkStandardNewMacro(vtkEventQtSlotConnect) + +// constructor +vtkEventQtSlotConnect::vtkEventQtSlotConnect() +{ + Connections = new vtkQtConnections; +} + + +vtkEventQtSlotConnect::~vtkEventQtSlotConnect() +{ + // clean out connections + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end(); ++iter) + { + delete (*iter); + } + + delete Connections; +} + +void vtkEventQtSlotConnect::Connect( + vtkObject* vtk_obj, unsigned long event, + const QObject* qt_obj, const char* slot, + void* client_data, float priority + , Qt::ConnectionType type) +{ + if (!vtk_obj || !qt_obj) + { + vtkErrorMacro("Cannot connect NULL objects."); + return; + } + vtkQtConnection* connection = new vtkQtConnection(this); + connection->SetConnection( + vtk_obj, event, qt_obj, slot, client_data, priority + , type); + Connections->push_back(connection); +} + + +void vtkEventQtSlotConnect::Disconnect(vtkObject* vtk_obj, unsigned long event, + const QObject* qt_obj, const char* slot, void* client_data) +{ + if (!vtk_obj) + { + vtkQtConnections::iterator iter; + for(iter=this->Connections->begin(); iter!=this->Connections->end(); ++iter) + { + delete (*iter); + } + this->Connections->clear(); + return; + } + bool all_info = true; + if(slot == NULL || qt_obj == NULL || event == vtkCommand::NoEvent) + all_info = false; + + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end();) + { + // if information matches, remove the connection + if((*iter)->IsConnection(vtk_obj, event, qt_obj, slot, client_data)) + { + delete (*iter); + iter = Connections->erase(iter); + // if user passed in all information, only remove one connection and quit + if(all_info) + iter = Connections->end(); + } + else + ++iter; + } +} + +void vtkEventQtSlotConnect::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if(Connections->empty()) + { + os << indent << "No Connections\n"; + } + else + { + os << indent << "Connections:\n"; + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end(); ++iter) + { + (*iter)->PrintSelf(os, indent.GetNextIndent()); + } + } +} + +void vtkEventQtSlotConnect::RemoveConnection(vtkQtConnection* conn) +{ + vtkQtConnections::iterator iter; + for(iter=this->Connections->begin(); iter!=this->Connections->end(); ++iter) + { + if(conn == *iter) + { + delete (*iter); + Connections->erase(iter); + return; + } + } +} + +int vtkEventQtSlotConnect::GetNumberOfConnections() const +{ + return static_cast(this->Connections->size()); +} + diff --git a/Modules/OpenView/vtkEventQtSlotConnect.h b/Modules/OpenView/vtkEventQtSlotConnect.h new file mode 100644 index 0000000000..c76de435dc --- /dev/null +++ b/Modules/OpenView/vtkEventQtSlotConnect.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +// .NAME vtkEventQtSlotConnect - Manage connections between VTK events and Qt slots. +// .SECTION Description +// vtkEventQtSlotConnect provides a way to manage connections between VTK events +// and Qt slots. +// Qt slots to connect with must have one of the following signatures: +// - MySlot() +// - MySlot(vtkObject* caller) +// - MySlot(vtkObject* caller, unsigned long vtk_event) +// - MySlot(vtkObject* caller, unsigned long vtk_event, void* client_data) +// - MySlot(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data) +// - MySlot(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data, vtkCommand*) + + +#ifndef VTK_EVENT_QT_SLOT_CONNECT +#define VTK_EVENT_QT_SLOT_CONNECT + +#include "vtkObject.h" +#include "vtkCommand.h" // for event defines +#include // for version info + +#include "OpenViewExports.h" + +class QObject; +class vtkQtConnections; +class vtkQtConnection; + +// manage connections between VTK object events and Qt slots +class OVCORE_EXPORT vtkEventQtSlotConnect : public vtkObject +{ + public: + static vtkEventQtSlotConnect* New(); + vtkTypeMacro(vtkEventQtSlotConnect, vtkObject) + + // Description: + // Print the current connections between VTK and Qt + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Connect a vtk object's event with a Qt object's slot. Multiple + // connections which are identical are treated as separate connections. + virtual void Connect(vtkObject* vtk_obj, unsigned long event, + const QObject* qt_obj, const char* slot, + void* client_data=NULL, float priority=0.0 + ,Qt::ConnectionType type = Qt::AutoConnection); + + // Description: + // Disconnect a vtk object from a qt object. + // Passing no arguments will disconnect all slots maintained by this object. + // Passing in only a vtk object will disconnect all slots from it. + // Passing only a vtk object and event, will disconnect all slots matching + // the vtk object and event. + // Passing all information in will match all information. + virtual void Disconnect( + vtkObject* vtk_obj=NULL, unsigned long event=vtkCommand::NoEvent, + const QObject* qt_obj=NULL, const char* slot = 0, void* client_data=NULL); + + // Description: + // Allow to query vtkEventQtSlotConnect to know if some Connect() have been + // setup and how many. + virtual int GetNumberOfConnections() const; + + protected: + vtkQtConnections* Connections; + friend class vtkQtConnection; + void RemoveConnection(vtkQtConnection*); + + vtkEventQtSlotConnect(); + ~vtkEventQtSlotConnect(); + + private: + // unimplemented + vtkEventQtSlotConnect(const vtkEventQtSlotConnect&); + void operator=(const vtkEventQtSlotConnect&); +}; + +#endif + diff --git a/Modules/OpenView/vtkQtConnection.cxx b/Modules/OpenView/vtkQtConnection.cxx new file mode 100644 index 0000000000..069c19b6fd --- /dev/null +++ b/Modules/OpenView/vtkQtConnection.cxx @@ -0,0 +1,151 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "vtkQtConnection.h" +#include "vtkEventQtSlotConnect.h" +#include "vtkCallbackCommand.h" + +#include +#include + +// constructor +vtkQtConnection::vtkQtConnection(vtkEventQtSlotConnect* owner) + : Owner(owner) +{ + this->Callback = vtkCallbackCommand::New(); + this->Callback->SetCallback(vtkQtConnection::DoCallback); + this->Callback->SetClientData(this); + this->VTKObject = 0; + this->QtObject = 0; + this->ClientData = 0; + this->VTKEvent = vtkCommand::NoEvent; +} + +// destructor, disconnect if necessary +vtkQtConnection::~vtkQtConnection() +{ + if(this->VTKObject) + { + this->VTKObject->RemoveObserver(this->Callback); + //Qt takes care of disconnecting slots + } + this->Callback->Delete(); +} + +void vtkQtConnection::DoCallback(vtkObject* vtk_obj, unsigned long event, + void* client_data, void* call_data) +{ + vtkQtConnection* conn = static_cast(client_data); + conn->Execute(vtk_obj, event, call_data); +} + + +// callback from VTK to emit signal +void vtkQtConnection::Execute(vtkObject* caller, unsigned long e, void* call_data) +{ + if(e != vtkCommand::DeleteEvent || + (e == vtkCommand::DeleteEvent && this->VTKEvent == vtkCommand::DeleteEvent)) + { + emit EmitExecute(caller, e, ClientData, call_data, this->Callback); + } + + if(e == vtkCommand::DeleteEvent) + { + this->Owner->Disconnect(this->VTKObject, this->VTKEvent, this->QtObject, + this->QtSlot.toUtf8().data(), + this->ClientData); + } +} + +bool vtkQtConnection::IsConnection(vtkObject* vtk_obj, unsigned long e, + const QObject* qt_obj, const char* slot, void* client_data) +{ + if(this->VTKObject != vtk_obj) + return false; + + if(e != vtkCommand::NoEvent && e != this->VTKEvent) + return false; + + if(qt_obj && qt_obj != this->QtObject) + return false; + + if(slot && this->QtSlot != slot) + return false; + + if(client_data && this->ClientData != client_data) + return false; + + return true; +} + +// set the connection +void vtkQtConnection::SetConnection( + vtkObject* vtk_obj, unsigned long e, + const QObject* qt_obj, const char* slot, + void* client_data, float priority + , Qt::ConnectionType type) +{ + // keep track of what we connected + this->VTKObject = vtk_obj; + this->QtObject = qt_obj; + this->VTKEvent = e; + this->ClientData = client_data; + this->QtSlot = slot; + + // make a connection between this and the vtk object + vtk_obj->AddObserver(e, this->Callback, priority); + + if(e != vtkCommand::DeleteEvent) + { + vtk_obj->AddObserver(vtkCommand::DeleteEvent, this->Callback); + } + + // make a connection between this and the Qt object + qt_obj->connect( + this, SIGNAL(EmitExecute(vtkObject*,unsigned long,void*,void*,vtkCommand*)), + slot + ,type); + QObject::connect(qt_obj, SIGNAL(destroyed(QObject*)), this, + SLOT(deleteConnection())); +} + +void vtkQtConnection::deleteConnection() +{ + this->Owner->RemoveConnection(this); +} + +void vtkQtConnection::PrintSelf(ostream& os, vtkIndent indent) +{ + if(this->VTKObject && this->QtObject) + { + os << indent << + this->VTKObject->GetClassName() << ":" << + vtkCommand::GetStringFromEventId(this->VTKEvent) << " <----> " << + this->QtObject->metaObject()->className() << "::" << + this->QtSlot.toUtf8().data() << "\n"; + } +} + diff --git a/Modules/OpenView/vtkQtConnection.h b/Modules/OpenView/vtkQtConnection.h new file mode 100644 index 0000000000..f9a90fa005 --- /dev/null +++ b/Modules/OpenView/vtkQtConnection.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +// .SECTION Description +// vtkQtConnection is an internal class. + + +#ifndef VTK_QT_CONNECTION +#define VTK_QT_CONNECTION + +#include "vtkObject.h" +#include "vtkCommand.h" // for event defines +#include "qobject.h" + +#include "OpenViewExports.h" + +class QObject; +class vtkCallbackCommand; +class vtkEventQtSlotConnect; + +// class for managing a single VTK/Qt connection +// not to be included in other projects +// only here for moc to process for vtkEventQtSlotConnect +class OVCORE_EXPORT vtkQtConnection : public QObject +{ + Q_OBJECT + + public: + + // constructor + vtkQtConnection(vtkEventQtSlotConnect* owner); + + // destructor, disconnect if necessary + ~vtkQtConnection(); + + // print function + void PrintSelf(ostream& os, vtkIndent indent); + + // callback from VTK to emit signal + void Execute(vtkObject* caller, unsigned long event, void* client_data); + + // set the connection + void SetConnection(vtkObject* vtk_obj, unsigned long event, + const QObject* qt_obj, const char* slot, + void* client_data, float priority=0.0 + ,Qt::ConnectionType type = Qt::AutoConnection); + + // check if a connection matches input parameters + bool IsConnection(vtkObject* vtk_obj, unsigned long event, + const QObject* qt_obj, const char* slot, + void* client_data); + + static void DoCallback(vtkObject* vtk_obj, unsigned long event, + void* client_data, void* call_data); + + signals: + // the qt signal for moc to take care of + void EmitExecute(vtkObject*, unsigned long, void* client_data, void* call_data, vtkCommand*); + + protected slots: + void deleteConnection(); + + protected: + + // the connection information + vtkObject* VTKObject; + vtkCallbackCommand* Callback; + const QObject* QtObject; + void* ClientData; + unsigned long VTKEvent; + QString QtSlot; + vtkEventQtSlotConnect* Owner; + + private: + vtkQtConnection(const vtkQtConnection&); + void operator=(const vtkQtConnection&); + +}; + +#endif + diff --git a/Modules/QmlMitk/CMakeLists.txt b/Modules/QmlMitk/CMakeLists.txt new file mode 100644 index 0000000000..53d1d560f9 --- /dev/null +++ b/Modules/QmlMitk/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE(QmlMitk + INCLUDE_DIRS InteractionLegacy + PACKAGE_DEPENDS Qt5 + DEPENDS Mitk OpenView) + diff --git a/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.cpp b/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.cpp new file mode 100644 index 0000000000..5eceb06a78 --- /dev/null +++ b/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.cpp @@ -0,0 +1,124 @@ +/*=================================================================== + +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 "QmitkEventAdapter.h" +#include +#include + +#include +#include + +mitk::MouseEvent +QmitkEventAdapter::AdaptMouseEvent(mitk::BaseRenderer* sender, QMouseEvent* mouseEvent) +{ + mitk::Point2D p; + p[0] = mouseEvent->x(); + p[1] = mouseEvent->y(); + + int modifiers = mouseEvent->modifiers(); + int state = 0; + + switch (mouseEvent->type()) + { + case QEvent::MouseButtonRelease: + state |= mouseEvent->button(); + break; + case QEvent::MouseMove: + state |= mouseEvent->buttons(); + break; + default: + break; + } + + if (modifiers & Qt::ShiftModifier) + state |= mitk::BS_ShiftButton; + if (modifiers & Qt::ControlModifier) + state |= mitk::BS_ControlButton; + if (modifiers & Qt::AltModifier) + state |= mitk::BS_AltButton; + if (modifiers & Qt::MetaModifier) + state |= mitk::BS_MetaButton; + if (modifiers & Qt::KeypadModifier) + state |= mitk::BS_Keypad; + + mitk::MouseEvent mitkEvent(sender, mouseEvent->type(), mouseEvent->button(), + state, mitk::Key_none, p); + + return mitkEvent; +} + +mitk::WheelEvent +QmitkEventAdapter::AdaptWheelEvent(mitk::BaseRenderer* sender, QWheelEvent* wheelEvent) +{ + mitk::Point2D p; + p[0] = wheelEvent->x(); + p[1] = wheelEvent->y(); + + int modifiers = wheelEvent->modifiers(); + int state = 0; + + state = wheelEvent->buttons(); + + if (modifiers & Qt::ShiftModifier) + state |= mitk::BS_ShiftButton; + if (modifiers & Qt::ControlModifier) + state |= mitk::BS_ControlButton; + if (modifiers & Qt::AltModifier) + state |= mitk::BS_AltButton; + if (modifiers & Qt::MetaModifier) + state |= mitk::BS_MetaButton; + if (modifiers & Qt::KeypadModifier) + state |= mitk::BS_Keypad; + + mitk::WheelEvent mitkEvent(sender, wheelEvent->type(), wheelEvent->buttons(), + state, mitk::Key_none, p, wheelEvent->delta()); + + return mitkEvent; +} + + +mitk::KeyEvent +QmitkEventAdapter::AdaptKeyEvent(mitk::BaseRenderer* sender, QKeyEvent* keyEvent, const QPoint& cp) +{ + int key = keyEvent->key(); + + // Those keycodes changed in Qt 4 + if (key >= 0x01000000 && key <= 0x01000060) + key -= (0x01000000 - 0x1000); + else if(key >= 0x01001120 && key <= 0x01001262) + key -= 0x01000000; + + mitk::Point2D p; + p[0] = cp.x(); + p[1] = cp.y(); + + int modifiers = keyEvent->modifiers(); + int state = 0; + if (modifiers & Qt::ShiftModifier) + state |= mitk::BS_ShiftButton; + if (modifiers & Qt::ControlModifier) + state |= mitk::BS_ControlButton; + if (modifiers & Qt::AltModifier) + state |= mitk::BS_AltButton; + if (modifiers & Qt::MetaModifier) + state |= mitk::BS_MetaButton; + //if (modifiers & Qt::KeypadModifier) + // state |= mitk::BS_Keypad; + + mitk::KeyEvent mke(sender, keyEvent->type(), mitk::BS_NoButton, state, key, keyEvent->text().toStdString(), p); + + return mke; +} diff --git a/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.h b/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.h new file mode 100644 index 0000000000..ac9c63362f --- /dev/null +++ b/Modules/QmlMitk/InteractionLegacy/QmitkEventAdapter.h @@ -0,0 +1,44 @@ +/*=================================================================== + +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 QMITKEVENTADAPTER_H_ +#define QMITKEVENTADAPTER_H_ + +#include + +#include +#include +#include +#include +#include + +/** + * \ingroup QmitkModule + * \deprecatedSince{2013_03} mitk::QmitkEventAdapter is deprecated. It will become + * obsolete. Adaption of events is now handeled (for Qt events) in QmitkRenderWindow. + * Refer to \see DataInteractionPage for general information about the concept of + * the new implementation + */ +class QmlMitk_EXPORT QmitkEventAdapter +{ +public: + + static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, QMouseEvent* mouseEvent); + static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, QWheelEvent* wheelEvent); + static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, QKeyEvent* keyEvent, const QPoint& point); +}; + +#endif /*QMITKEVENTADAPTER_H_*/ diff --git a/Modules/QmlMitk/QmlMitkBigRenderLock.cpp b/Modules/QmlMitk/QmlMitkBigRenderLock.cpp new file mode 100644 index 0000000000..0db66d7efd --- /dev/null +++ b/Modules/QmlMitk/QmlMitkBigRenderLock.cpp @@ -0,0 +1,48 @@ +#include "QmlMitkBigRenderLock.h" + +#include "QVTKQuickItem.h" + +QMutex& QmlMitkBigRenderLock::GetMutex() +{ + static QMutex globalRenderingLock; + return globalRenderingLock; +} + +QmlMitkBigRenderLock::QmlMitkBigRenderLock(QObject* parent) +:QObject(parent) +{ +} + +bool QmlMitkBigRenderLock::eventFilter(QObject* /*obj*/, QEvent* /*event*/) +{ + /* + TODO + + this should BLOCK during rendering, i.e. + + it should acquire a mutex lock which is also acquired by the rendering method in QVTKQuickItem + + TODO: + + THIS MUST BE CHANGED! + + It is NOT sufficient to delay signal delivery, BUT we must block rendering until the signal is completely processed. + TODO: what would happen if a signal receiver calls rendering->ForceImmediateUpdateAll ? + + + + */ + + if ( GetMutex().tryLock() ) + { + // ok, let's continue + } + else + { + GetMutex().lock(); + } + + GetMutex().unlock(); + + return false; // don't actually filter/remove events +} diff --git a/Modules/QmlMitk/QmlMitkBigRenderLock.h b/Modules/QmlMitk/QmlMitkBigRenderLock.h new file mode 100644 index 0000000000..7037e48fba --- /dev/null +++ b/Modules/QmlMitk/QmlMitkBigRenderLock.h @@ -0,0 +1,21 @@ +#ifndef QmlMitkBigRenderLock_h +#define QmlMitkBigRenderLock_h + +#include + +#include "QmlMitkExports.h" + +class QmlMitk_EXPORT QmlMitkBigRenderLock : public QObject +{ + Q_OBJECT + public: + + static QMutex& GetMutex(); + + QmlMitkBigRenderLock(QObject* parent = 0); + + protected: + bool eventFilter(QObject *obj, QEvent *event); +}; + +#endif diff --git a/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.cpp b/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.cpp new file mode 100644 index 0000000000..c7089fb80d --- /dev/null +++ b/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.cpp @@ -0,0 +1,102 @@ + +#include "QmlMitkFourRenderWindowWidget.h" + +#include "mitkDisplayInteractor.h" + +#include "usGetModuleContext.h" + +#include + +#include + +QmlMitkFourRenderWindowWidget::QmlMitkFourRenderWindowWidget(QQuickItem* parent) +: QQuickItem(parent) +, m_ChildrenContainer(NULL) +, m_RenderItemAxial(NULL) +, m_RenderItemSagittal(NULL) +, m_RenderItemFrontal(NULL) +, m_RenderItem3D(NULL) +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl("qrc:///MITK/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.qml")); + m_ChildrenContainer = qobject_cast( component.create() ); + + if (m_ChildrenContainer) + { + QQmlProperty::write(m_ChildrenContainer, "parent", QVariant::fromValue(this)); + QQmlEngine::setObjectOwnership(m_ChildrenContainer, QQmlEngine::CppOwnership); + + SetupWidget(m_ChildrenContainer); + } + else + { + throw std::logic_error("Initialization of QmlMitkFourRenderWindowWidget went dead wrong. Check code..."); + } +} + +QmlMitkFourRenderWindowWidget::~QmlMitkFourRenderWindowWidget() +{ + if (m_ChildrenContainer) + { + m_ChildrenContainer->deleteLater(); + } +} + +void QmlMitkFourRenderWindowWidget::SetupWidget( QQuickItem* parent ) +{ + m_RenderItemAxial = parent->findChild("mitkRenderItemAxial"); + m_RenderItemSagittal = parent->findChild("mitkRenderItemSagittal"); + m_RenderItemFrontal = parent->findChild("mitkRenderItemFrontal"); + m_RenderItem3D = parent->findChild("mitkRenderItem3D"); + + if (m_RenderItemAxial && m_RenderItemSagittal && m_RenderItemFrontal && m_RenderItem3D) + { + m_RenderItemAxial->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard2D ); + m_RenderItemAxial->GetRenderer()->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Axial ); + + m_RenderItemSagittal->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard2D ); + m_RenderItemSagittal->GetRenderer()->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Sagittal ); + + m_RenderItemFrontal->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard2D ); + m_RenderItemFrontal->GetRenderer()->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Frontal ); + + m_RenderItem3D->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D ); + m_RenderItem3D->GetRenderer()->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Original ); + + InitializeMoveZoomInteraction(); + } +} + +void QmlMitkFourRenderWindowWidget::InitializeMoveZoomInteraction() +{ + static mitk::DisplayInteractor::Pointer m_ZoomScroller = mitk::DisplayInteractor::New(); + m_ZoomScroller->LoadStateMachine("DisplayInteraction.xml"); + m_ZoomScroller->SetEventConfig("DisplayConfigMITK.xml"); + + us::ModuleContext* context = us::GetModuleContext(); + context->RegisterService( m_ZoomScroller.GetPointer() ); +} + + +void QmlMitkFourRenderWindowWidget::SetDataStorage( mitk::DataStorage::Pointer storage ) +{ + m_DataStorage = storage; + + // TODO file bug: planes rendering 2D REQUIRES a parent node for all plane geometries! the mapper should just not care if it cannot find others! + // TODO make this conditional, only add if not yet preset... + mitk::DataNode::Pointer planesNodeParent = mitk::DataNode::New(); + m_DataStorage->Add( planesNodeParent ); + + m_RenderItemAxial->SetPlaneNodeParent( planesNodeParent ); + m_RenderItemAxial->GetRenderer()->SetDataStorage( m_DataStorage ); + + m_RenderItemSagittal->SetPlaneNodeParent( planesNodeParent ); + m_RenderItemSagittal->GetRenderer()->SetDataStorage( m_DataStorage ); + + m_RenderItemFrontal->SetPlaneNodeParent( planesNodeParent ); + m_RenderItemFrontal->GetRenderer()->SetDataStorage( m_DataStorage ); + + m_RenderItem3D->SetPlaneNodeParent( planesNodeParent ); + m_RenderItem3D->GetRenderer()->SetDataStorage( m_DataStorage ); +} + diff --git a/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.h b/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.h new file mode 100644 index 0000000000..a9527048aa --- /dev/null +++ b/Modules/QmlMitk/QmlMitkFourRenderWindowWidget.h @@ -0,0 +1,50 @@ +#ifndef QmlMitkFourRenderWindowWidget_h +#define QmlMitkFourRenderWindowWidget_h + +#include + +#include "QmlMitkRenderWindowItem.h" + +#include "mitkDataStorage.h" + +#include "QmlMitkExports.h" + +class QmlMitk_EXPORT QmlMitkFourRenderWindowWidget : public QQuickItem +{ + Q_OBJECT + +public: + + QmlMitkFourRenderWindowWidget(QQuickItem* parent = 0); + virtual ~QmlMitkFourRenderWindowWidget(); + + void SetDataStorage( mitk::DataStorage::Pointer storage ); + +signals: + +public slots: + +protected slots: + +protected: + + virtual void SetupWidget( QQuickItem* parent ); + + virtual void InitializeMoveZoomInteraction(); + + mitk::DataStorage::Pointer m_DataStorage; + +private slots: + +private: + + QQuickItem* m_ChildrenContainer; + + QmlMitkRenderWindowItem* m_RenderItemAxial; + QmlMitkRenderWindowItem* m_RenderItemSagittal; + QmlMitkRenderWindowItem* m_RenderItemFrontal; + QmlMitkRenderWindowItem* m_RenderItem3D; + +}; + +#endif diff --git a/Modules/QmlMitk/QmlMitkRenderWindowItem.cpp b/Modules/QmlMitk/QmlMitkRenderWindowItem.cpp new file mode 100644 index 0000000000..0f96ef6647 --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderWindowItem.cpp @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QmlMitkRenderWindowItem.h" + +#include + +#include +#include +#include +#include + +// MITK event types +#include "mitkMousePressEvent.h" +#include "mitkMouseMoveEvent.h" +#include "mitkMouseDoubleClickEvent.h" +#include "mitkMouseReleaseEvent.h" +#include "mitkInteractionKeyEvent.h" +#include "mitkMouseWheelEvent.h" +#include "mitkInternalEvent.h" +#include "mitkGeometry2DDataMapper2D.h" + +#include "QmlMitkBigRenderLock.h" + +#define INTERACTION_LEGACY // TODO: remove INTERACTION_LEGACY! + +#if defined INTERACTION_LEGACY + #include "InteractionLegacy/QmitkEventAdapter.h" + #include "mitkGlobalInteraction.h" +#endif + +QmlMitkRenderWindowItem* QmlMitkRenderWindowItem::GetInstanceForVTKRenderWindow( vtkRenderWindow* rw ) +{ + return GetInstances()[rw]; +} + +QMap& QmlMitkRenderWindowItem::GetInstances() +{ + static QMap s_Instances; + return s_Instances; +} + + +QmlMitkRenderWindowItem +::QmlMitkRenderWindowItem(QQuickItem* parent, + const QString& name, + mitk::VtkPropRenderer* /*renderer*/, + mitk::RenderingManager* renderingManager) +: QVTKQuickItem(parent) +{ + mitk::RenderWindowBase::Initialize( renderingManager, name.toStdString().c_str() ); + + /* from QmitkRenderWindow. Required? + setFocusPolicy(Qt::StrongFocus); + setMouseTracking(true); + */ + + GetInstances()[QVTKQuickItem::GetRenderWindow()] = this; +} + +// called from QVTKQuickItem when window is painted for the first time! +void QmlMitkRenderWindowItem::init() +{ + QVTKQuickItem::init(); + + mitk::DataStorage::Pointer m_DataStorage = mitk::RenderWindowBase::GetRenderer()->GetDataStorage(); + if (m_DataStorage.IsNotNull()) + { + mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); + } + + // TODO the following code needs to be moved to a multi-widget item + if ( mitk::RenderWindowBase::GetRenderer()->GetMapperID() == mitk::BaseRenderer::Standard2D ) + { + this->SetCrossHairPositioningOnClick(true); + } + + if ( mitk::RenderWindowBase::GetRenderer()->GetMapperID() == mitk::BaseRenderer::Standard2D + && m_DataStorage.IsNotNull() ) + { + + mitk::DataNode::Pointer planeNode = mitk::RenderWindowBase::GetRenderer()->GetCurrentWorldGeometry2DNode(); + switch ( mitk::RenderWindowBase::GetRenderer()->GetSliceNavigationController()->GetDefaultViewDirection() ) + { + case mitk::SliceNavigationController::Axial: + planeNode->SetColor(1.0,0.0,0.0); + break; + case mitk::SliceNavigationController::Sagittal: + planeNode->SetColor(0.0,1.0,0.0); + break; + case mitk::SliceNavigationController::Frontal: + planeNode->SetColor(0.0,0.0,1.0); + break; + default: + planeNode->SetColor(1.0,1.0,0.0); + } + planeNode->SetProperty("layer", mitk::IntProperty::New(1000) ); + planeNode->SetProperty("visible", mitk::BoolProperty::New(true) ); + planeNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); + + mitk::Geometry2DDataMapper2D::Pointer mapper = mitk::Geometry2DDataMapper2D::New(); + mapper->SetDatastorageAndGeometryBaseNode( m_DataStorage, m_PlaneNodeParent ); + planeNode->SetMapper( mitk::BaseRenderer::Standard2D, mapper ); + + m_DataStorage->Add( planeNode, m_PlaneNodeParent ); + } +} + +void QmlMitkRenderWindowItem::InitView( mitk::BaseRenderer::MapperSlotId mapperID, + mitk::SliceNavigationController::ViewDirection viewDirection ) +{ + m_MapperID = mapperID; + m_ViewDirection = viewDirection; +} + + +void QmlMitkRenderWindowItem::SetDataStorage(mitk::DataStorage::Pointer storage) +{ + m_DataStorage = storage; +} + +mitk::Point2D QmlMitkRenderWindowItem::GetMousePosition(QMouseEvent* me) const +{ + + mitk::Point2D point; + point[0] = me->x(); + point[1] = me->y(); + return point; +} + +mitk::Point2D QmlMitkRenderWindowItem::GetMousePosition(QWheelEvent* we) const +{ + mitk::Point2D point; + point[0] = we->x(); + point[1] = we->y(); + return point; +} + +mitk::InteractionEvent::MouseButtons QmlMitkRenderWindowItem::GetEventButton(QMouseEvent* me) const +{ + mitk::InteractionEvent::MouseButtons eventButton; + switch (me->button()) + { + case Qt::LeftButton: + eventButton = mitk::InteractionEvent::LeftMouseButton; + break; + case Qt::RightButton: + eventButton = mitk::InteractionEvent::RightMouseButton; + break; + case Qt::MidButton: + eventButton = mitk::InteractionEvent::MiddleMouseButton; + break; + default: + eventButton = mitk::InteractionEvent::NoButton; + break; + } + return eventButton; +} + +mitk::InteractionEvent::MouseButtons QmlMitkRenderWindowItem::GetButtonState(QMouseEvent* me) const +{ + mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; + + if (me->buttons() & Qt::LeftButton) + { + buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; + } + if (me->buttons() & Qt::RightButton) + { + buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; + } + if (me->buttons() & Qt::MidButton) + { + buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; + } + return buttonState; +} + +mitk::InteractionEvent::ModifierKeys QmlMitkRenderWindowItem::GetModifiers(QInputEvent* me) const +{ + mitk::InteractionEvent::ModifierKeys modifiers = mitk::InteractionEvent::NoKey; + + if (me->modifiers() & Qt::ALT) + { + modifiers = modifiers | mitk::InteractionEvent::AltKey; + } + if (me->modifiers() & Qt::CTRL) + { + modifiers = modifiers | mitk::InteractionEvent::ControlKey; + } + if (me->modifiers() & Qt::SHIFT) + { + modifiers = modifiers | mitk::InteractionEvent::ShiftKey; + } + return modifiers; +} + +mitk::InteractionEvent::MouseButtons QmlMitkRenderWindowItem::GetButtonState(QWheelEvent* we) const +{ + mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; + + if (we->buttons() & Qt::LeftButton) + { + buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; + } + if (we->buttons() & Qt::RightButton) + { + buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; + } + if (we->buttons() & Qt::MidButton) + { + buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; + } + return buttonState; +} + + +void QmlMitkRenderWindowItem::mousePressEvent(QMouseEvent* me) +{ + mitk::MousePressEvent::Pointer mPressEvent = + mitk::MousePressEvent::New(mitk::RenderWindowBase::GetRenderer(), GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); + +#if defined INTERACTION_LEGACY + bool modernInteractorHandledEvent = +#endif + mitk::RenderWindowBase::HandleEvent(mPressEvent.GetPointer()); +#if defined INTERACTION_LEGACY + if (!modernInteractorHandledEvent) + { + mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(mitk::RenderWindowBase::GetRenderer(), me)); + mitk::RenderWindowBase::mousePressMitkEvent(&myevent); + } +#endif + + QVTKQuickItem::mousePressEvent(me); + +// if (m_ResendQtEvents) +// me->ignore(); +} + +void QmlMitkRenderWindowItem::mouseReleaseEvent(QMouseEvent* me) +{ + mitk::MouseReleaseEvent::Pointer mReleaseEvent = + mitk::MouseReleaseEvent::New(mitk::RenderWindowBase::GetRenderer(), GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); + +#if defined INTERACTION_LEGACY + bool modernInteractorHandledEvent = +#endif + mitk::RenderWindowBase::HandleEvent(mReleaseEvent.GetPointer()); +#if defined INTERACTION_LEGACY + if (!modernInteractorHandledEvent) + { + mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(mitk::RenderWindowBase::GetRenderer(), me)); + mitk::RenderWindowBase::mouseReleaseMitkEvent(&myevent); + } +#endif + + QVTKQuickItem::mouseReleaseEvent(me); + +// if (m_ResendQtEvents) +// me->ignore(); +} + +void QmlMitkRenderWindowItem::mouseMoveEvent(QMouseEvent* me) +{ + mitk::MouseMoveEvent::Pointer mMoveEvent = + mitk::MouseMoveEvent::New(mitk::RenderWindowBase::GetRenderer(), GetMousePosition(me), GetButtonState(me), GetModifiers(me)); + +#if defined INTERACTION_LEGACY + bool modernInteractorHandledEvent = +#endif + mitk::RenderWindowBase::HandleEvent(mMoveEvent.GetPointer()); +#if defined INTERACTION_LEGACY + if (!modernInteractorHandledEvent) + { + mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(mitk::RenderWindowBase::GetRenderer(), me)); + mitk::RenderWindowBase::mouseMoveMitkEvent(&myevent); + } +#endif + + QVTKQuickItem::mouseMoveEvent(me); + +// TODO: why was this not put here initially? What is special about mouse move? +// if (m_ResendQtEvents) +// me->ignore(); +} + +void QmlMitkRenderWindowItem::wheelEvent(QWheelEvent *we) +{ + mitk::MouseWheelEvent::Pointer mWheelEvent = + mitk::MouseWheelEvent::New(mitk::RenderWindowBase::GetRenderer(), GetMousePosition(we), GetButtonState(we), GetModifiers(we), we->delta()); + +#if defined INTERACTION_LEGACY + bool modernInteractorHandledEvent = +#endif + mitk::RenderWindowBase::HandleEvent(mWheelEvent.GetPointer()); +#if defined INTERACTION_LEGACY + if (!modernInteractorHandledEvent) + { // TODO: INTERACTION_LEGACY + mitk::WheelEvent myevent(QmitkEventAdapter::AdaptWheelEvent(mitk::RenderWindowBase::GetRenderer(), we)); + mitk::RenderWindowBase::wheelMitkEvent(&myevent); + } +#endif + + QVTKQuickItem::wheelEvent(we); + +// if (m_ResendQtEvents) +// we->ignore(); +} + + +void QmlMitkRenderWindowItem::prepareForRender() +{ +// Adjust camera is kaputt wenn nicht der renderingmanager dem vtkprop bescheid sagt! +// this is just a workaround + QmlMitkBigRenderLock::GetMutex().lock(); + mitk::RenderWindowBase::GetRenderer()->ForceImmediateUpdate(); +} + +void QmlMitkRenderWindowItem::cleanupAfterRender() +{ + QmlMitkBigRenderLock::GetMutex().unlock(); +} + +void QmlMitkRenderWindowItem::SetCrossHairPositioningOnClick(bool enabled) +{ + if (enabled) + { + mitk::GlobalInteraction::GetInstance()->AddListener( mitk::RenderWindowBase::GetSliceNavigationController() ); + } + else + { + mitk::GlobalInteraction::GetInstance()->RemoveListener( mitk::RenderWindowBase::GetSliceNavigationController() ); + } +} + +void QmlMitkRenderWindowItem::SetPlaneNodeParent( mitk::DataNode::Pointer node ) +{ + m_PlaneNodeParent = node; +} + +void QmlMitkRenderWindowItem::geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry) +{ + QVTKQuickItem::geometryChanged(newGeometry, oldGeometry); + + this->resizeMitkEvent( newGeometry.width(), newGeometry.height() ); +} + +vtkRenderWindow* QmlMitkRenderWindowItem::GetVtkRenderWindow() +{ + return QVTKQuickItem::GetRenderWindow(); +} + +vtkRenderWindowInteractor* QmlMitkRenderWindowItem::GetVtkRenderWindowInteractor() +{ + return QVTKQuickItem::GetInteractor(); +} + + diff --git a/Modules/QmlMitk/QmlMitkRenderWindowItem.h b/Modules/QmlMitk/QmlMitkRenderWindowItem.h new file mode 100644 index 0000000000..8ab3e0c368 --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderWindowItem.h @@ -0,0 +1,79 @@ +#ifndef QmlMitkRenderWindowItem_h +#define QmlMitkRenderWindowItem_h + +#include + +#include "mitkRenderWindowBase.h" + +#include + +#include "QmlMitkExports.h" + +class QmlMitk_EXPORT QmlMitkRenderWindowItem : public QVTKQuickItem, public mitk::RenderWindowBase +{ + Q_OBJECT + +public: + static QmlMitkRenderWindowItem* GetInstanceForVTKRenderWindow( vtkRenderWindow* rw ); + + QmlMitkRenderWindowItem(QQuickItem* parent = 0, + const QString& name = "QML render window", + mitk::VtkPropRenderer* renderer = NULL, + mitk::RenderingManager* renderingManager = NULL); + + virtual vtkRenderWindow* GetVtkRenderWindow(); + virtual vtkRenderWindowInteractor* GetVtkRenderWindowInteractor(); + + void SetDataStorage(mitk::DataStorage::Pointer storage); + + void InitView( mitk::BaseRenderer::MapperSlotId mapperID, + mitk::SliceNavigationController::ViewDirection viewDirection ); + + void SetPlaneNodeParent( mitk::DataNode::Pointer node ); + + void SetCrossHairPositioningOnClick(bool enabled); + +signals: + +public slots: + +protected slots: + +protected: + + virtual void init(); + virtual void prepareForRender(); + virtual void cleanupAfterRender(); + + mitk::Point2D GetMousePosition(QMouseEvent* me) const; + mitk::Point2D GetMousePosition(QWheelEvent* we) const; + mitk::InteractionEvent::MouseButtons GetEventButton(QMouseEvent* me) const; + mitk::InteractionEvent::MouseButtons GetButtonState(QMouseEvent* me) const; + mitk::InteractionEvent::ModifierKeys GetModifiers(QInputEvent* me) const; + mitk::InteractionEvent::MouseButtons GetButtonState(QWheelEvent* we) const; + void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry); // !? + + virtual void mousePressEvent(QMouseEvent* e); + virtual void mouseReleaseEvent(QMouseEvent* e); + virtual void mouseMoveEvent(QMouseEvent* e); + virtual void wheelEvent(QWheelEvent* e); + +private slots: + +private: + mitk::DataStorage::Pointer m_DataStorage; + mitk::DataNode::Pointer m_PlaneNodeParent; + + mitk::BaseRenderer::MapperSlotId m_MapperID; + mitk::SliceNavigationController::ViewDirection m_ViewDirection; + + + QTimer m_Animation; + + vtkSmartPointer m_connect; + + static QMap& GetInstances(); + +}; + +#endif diff --git a/Modules/QmlMitk/QmlMitkRenderingManager.cpp b/Modules/QmlMitk/QmlMitkRenderingManager.cpp new file mode 100644 index 0000000000..0e6b7697fc --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderingManager.cpp @@ -0,0 +1,131 @@ +/*=================================================================== + +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 "QmlMitkRenderingManager.h" +#include "QmlMitkRenderWindowItem.h" + + +#include "mitkGeometry3D.h" +#include "mitkBaseRenderer.h" +#include "mitkSliceNavigationController.h" + +#include +#include + + +QmlMitkRenderingManager +::QmlMitkRenderingManager() +:pendingTimerCallbacks(0) +{ +} + +QmlMitkRenderingManager +::~QmlMitkRenderingManager() +{ +} + +void +QmlMitkRenderingManager +::GenerateRenderingRequestEvent() +{ + QCoreApplication::postEvent( this, new QmlMitkRenderingRequestEvent ); +} + + +void +QmlMitkRenderingManager +::StartOrResetTimer() +{ + QTimer::singleShot(200, this, SLOT(TimerCallback())); + pendingTimerCallbacks++; +} + +void +QmlMitkRenderingManager +::TimerCallback() +{ + if(!--pendingTimerCallbacks) + { + this->ExecutePendingHighResRenderingRequest(); + } +} + +#include + +bool +QmlMitkRenderingManager +::event( QEvent *event ) +{ + if ( event->type() == (QEvent::Type) QmlMitkRenderingRequestEvent::RenderingRequest ) + { + // Directly process all pending rendering requests + //this->ExecutePendingRequests(); + this->MyUpdateExecutePendingRequests(); + + return true; + } + + return false; +} + +#include "QVTKQuickItem.h" + +void QmlMitkRenderingManager::MyUpdateExecutePendingRequests() +{ + m_UpdatePending = false; + + // Satisfy all pending update requests + RenderWindowList::iterator it; + int i = 0; + for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it, ++i ) + { + if ( it->second == RENDERING_REQUESTED ) + { + vtkRenderWindow* renderWindow = it->first; + + // If the renderWindow is not valid, we do not want to inadvertantly create + // an entry in the m_RenderWindowList map. It is possible if the user is + // regularly calling AddRenderer and RemoveRenderer for a rendering update + // to come into this method with a renderWindow pointer that is valid in the + // sense that the window does exist within the application, but that + // renderWindow has been temporarily removed from this RenderingManager for + // performance reasons. + if (m_RenderWindowList.find( renderWindow ) == m_RenderWindowList.end()) + { + continue; + } + + // Erase potentially pending requests for this window + m_RenderWindowList[renderWindow] = RENDERING_INACTIVE; + + m_UpdatePending = false; + + // Immediately repaint this window (implementation platform specific) + // If the size is 0 it crahses + int *size = renderWindow->GetSize(); + if ( 0 != size[0] && 0 != size[1] ) + { + QmlMitkRenderWindowItem* qqi = QmlMitkRenderWindowItem::GetInstanceForVTKRenderWindow( renderWindow ); + if (qqi) + { + qqi->update(); + } + } + } + } +} + + diff --git a/Modules/QmlMitk/QmlMitkRenderingManager.h b/Modules/QmlMitk/QmlMitkRenderingManager.h new file mode 100644 index 0000000000..fd5eac1599 --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderingManager.h @@ -0,0 +1,85 @@ +/*=================================================================== + +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 QmlMitkRenderingManager_h +#define QmlMitkRenderingManager_h + +#include + +#include "mitkRenderingManager.h" + +#include +#include + +class QmlMitkRenderingManagerFactory; + +/** + * \ingroup QmlMitkModule + * \brief Qt/Qml specific implementation of mitk::RenderingManager. + * + * This implementation defines a QmlMitkRenderingRequestEvent to realize the + * rendering request process. The event is put into Qt's event loop to + * receive it back in the GUI thread where we are allowed to do rendering. + * + */ +class QmlMitk_EXPORT QmlMitkRenderingManager : public QObject, public mitk::RenderingManager +{ + Q_OBJECT + +public: + + mitkClassMacro( QmlMitkRenderingManager, mitk::RenderingManager ); + virtual ~QmlMitkRenderingManager(); + + virtual bool event( QEvent *event ); + +protected: + + itkFactorylessNewMacro(Self); + + QmlMitkRenderingManager(); + + virtual void GenerateRenderingRequestEvent(); + + virtual void StartOrResetTimer(); + + int pendingTimerCallbacks; + + protected slots: + + void TimerCallback(); + +private: + + friend class QmlMitkRenderingManagerFactory; + + void MyUpdateExecutePendingRequests(); +}; + +class QmlMitkRenderingRequestEvent : public QEvent +{ +public: + enum Type + { + RenderingRequest = QEvent::MaxUser - 1024 + }; + + QmlMitkRenderingRequestEvent() + : QEvent( (QEvent::Type) RenderingRequest ) {}; +}; + +#endif /* MITKRenderingManager_H_HEADER_INCLUDED_C135A197 */ diff --git a/Modules/QmlMitk/QmlMitkRenderingManagerFactory.cpp b/Modules/QmlMitk/QmlMitkRenderingManagerFactory.cpp new file mode 100644 index 0000000000..11d7f21292 --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderingManagerFactory.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +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 "QmlMitkRenderingManagerFactory.h" +#include "QmlMitkRenderingManager.h" + +QmlMitkRenderingManagerFactory +::QmlMitkRenderingManagerFactory() +{ + mitk::RenderingManager::SetFactory( this ); +} + +QmlMitkRenderingManagerFactory +::~QmlMitkRenderingManagerFactory() +{ +} + +mitk::RenderingManager::Pointer +QmlMitkRenderingManagerFactory +::CreateRenderingManager() const +{ + QmlMitkRenderingManager::Pointer specificSmartPtr = QmlMitkRenderingManager::New(); + return specificSmartPtr.GetPointer(); +} diff --git a/Modules/QmlMitk/QmlMitkRenderingManagerFactory.h b/Modules/QmlMitk/QmlMitkRenderingManagerFactory.h new file mode 100644 index 0000000000..1d0917e6f4 --- /dev/null +++ b/Modules/QmlMitk/QmlMitkRenderingManagerFactory.h @@ -0,0 +1,48 @@ +/*=================================================================== + +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 QmlMitkRenderingManagerFactory_h +#define QmlMitkRenderingManagerFactory_h + +#include + +#include "mitkRenderingManagerFactory.h" + +/** + * \ingroup QmlMitkModule + * \brief Qt specific implementation of mitk::RenderingManagerFactory. + * + * This class create QmlMitkRenderingManager instances via + * CreateRenderingManager(). + * + */ +class QmlMitk_EXPORT QmlMitkRenderingManagerFactory : public mitk::RenderingManagerFactory +{ +public: + + QmlMitkRenderingManagerFactory(); + + ~QmlMitkRenderingManagerFactory(); + + virtual mitk::RenderingManager::Pointer CreateRenderingManager() const; + +private: + +}; + + +#endif diff --git a/Modules/QmlMitk/files.cmake b/Modules/QmlMitk/files.cmake new file mode 100644 index 0000000000..bf9744dc4b --- /dev/null +++ b/Modules/QmlMitk/files.cmake @@ -0,0 +1,27 @@ +set(CPP_FILES + QmlMitkRenderWindowItem.cpp + QmlMitkRenderingManager.cpp + QmlMitkRenderingManagerFactory.cpp + InteractionLegacy/QmitkEventAdapter.cpp + QmlMitkBigRenderLock.cpp + QmlMitkFourRenderWindowWidget.cpp +) + +set(MOC_H_FILES + QmlMitkRenderWindowItem.h + QmlMitkRenderingManager.h + QmlMitkBigRenderLock.h + QmlMitkFourRenderWindowWidget.h +) + +# THIS is normally done by MITK_CREATE_MODULE. +# BUT we do not use the MITK definition of a "Qt module" +# because we need Qt 5 instead of Qt 4 (the MITK default) +qt5_wrap_cpp(moc_SRC ${MOC_H_FILES}) +set(CPP_FILES ${CPP_FILES} ${moc_SRC}) + +set(UI_FILES +) + +set(QRC_FILES +) diff --git a/README.md b/README.md new file mode 120000 index 0000000000..72dca0398c --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Examples/QuickRender/README.md \ No newline at end of file