diff --git a/Modules/DicomRT/include/mitkRTConstants.h b/Modules/DicomRT/include/mitkRTConstants.h index 54c1009e55..e5d1990407 100644 --- a/Modules/DicomRT/include/mitkRTConstants.h +++ b/Modules/DicomRT/include/mitkRTConstants.h @@ -1,87 +1,89 @@ /*=================================================================== 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 _MITK_RT_CONSTANTS_H_ #define _MITK_RT_CONSTANTS_H_ #include #include "MitkDicomRTExports.h" namespace mitk { -struct MITKDICOMRT_EXPORT Constants + +struct MITKDICOMRT_EXPORT RTConstants + { /** * Name of the property that indicates if a data/node is a dose. */ static const std::string DOSE_PROPERTY_NAME; /** * Name of the property that encodes the prescribed dose associated with the data node * If a RTPLAN file exists the value can be extracted from the tag (300A,0026) - Target Prescription Dose in the plan file. */ static const std::string PRESCRIBED_DOSE_PROPERTY_NAME; /** * Name of the property that encodes the reference dose that should be used for relative dose vizualization/evaluation purpose. * It is often the prescribed dose but may differ e.g. when to dose distributions sould be compared using the same reference. */ static const std::string REFERENCE_DOSE_PROPERTY_NAME; /** * Name of the property that encodes the optional string property holding the information from the tag (3004,0004) - Dose Type. * This contains useful information for medical doctors */ static const std::string DOSE_TYPE_PROPERTY_NAME; /** * Name of the property that encodes the optional string property holding the information from the tag (3004,000A) - Dose Summation Type. * This contains useful information for medical doctors */ static const std::string DOSE_SUMMATION_TYPE_PROPERTY_NAME; /** * Name of the property that encodes the number of fractions. * It is for example in DICOM stored in tag (300A,0078) - Number of Fractions Prescribed (from the RTPLAN file if this file exists). * This value could be used to further scale the dose according to dose summation type. * For example a given plan consists of 8 fractions. Scaling the fraction dose by 8 gives the complete planned dose. */ static const std::string DOSE_FRACTION_COUNT_PROPERTY_NAME; /** * Name of the property that encodes if the iso line rendering should be activated for the node. */ static const std::string DOSE_SHOW_ISOLINES_PROPERTY_NAME; /** * Name of the property that encodes if the color wash rendering should be activated for the node. */ static const std::string DOSE_SHOW_COLORWASH_PROPERTY_NAME; /** * Name of the property that encodes if the set of iso levels should be used to visualize the dose distribution. */ static const std::string DOSE_ISO_LEVELS_PROPERTY_NAME; /** * Name of the property that encodes user defined iso values that mark special dose values in the distribution. */ static const std::string DOSE_FREE_ISO_VALUES_PROPERTY_NAME; }; } #endif diff --git a/Modules/DicomRT/src/Rendering/mitkDoseImageVtkMapper2D.cpp b/Modules/DicomRT/src/Rendering/mitkDoseImageVtkMapper2D.cpp index 099a2ebb9b..805404a31e 100644 --- a/Modules/DicomRT/src/Rendering/mitkDoseImageVtkMapper2D.cpp +++ b/Modules/DicomRT/src/Rendering/mitkDoseImageVtkMapper2D.cpp @@ -1,1102 +1,1102 @@ /*=================================================================== 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. ===================================================================*/ //MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkImageStatisticsHolder.h" #include "mitkPlaneClipping.h" //MITK Rendering #include "mitkDoseImageVtkMapper2D.h" #include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" #include "vtkNeverTranslucentTexture.h" //VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ITK #include mitk::DoseImageVtkMapper2D::DoseImageVtkMapper2D() { } mitk::DoseImageVtkMapper2D::~DoseImageVtkMapper2D() { //The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) is listening to this event, //in order to delete the images from the 3D RW. this->InvokeEvent( itk::DeleteEvent() ); } //set the two points defining the textured plane according to the dimension and spacing void mitk::DoseImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct //plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); //These two points define the axes of the plane in combination with the origin. //Point 1 is the x-axis and point 2 the y-axis. //Each plane is transformed according to the view (axial, coronal and saggital) afterwards. localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) } float mitk::DoseImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) { //get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined float depth = -maxRange*0.01; // divide by 100 int layer = 0; GetDataNode()->GetIntProperty( "layer", layer, renderer); //add the layer property for each image to render images with a higher layer on top of the others depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) if(depth > 0.0f) { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } const mitk::Image* mitk::DoseImageVtkMapper2D::GetInput( void ) { return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); } vtkProp* mitk::DoseImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } void mitk::DoseImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); mitk::DataNode* datanode = this->GetDataNode(); if ( input == NULL || input->IsInitialized() == false ) { return; } //check if there is a valid worldGeometry const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry(); if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) { return; } input->Update(); // early out if there is no intersection of the current rendering geometry // and the geometry of the image that is to be rendered. if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) ) { // set image to NULL, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 localStorage->m_ReslicedImage = NULL; localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); return; } //set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); //set the transformation of the image to adapt reslice axis localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) ); //is the geometry of the slice based on the input image or the worldgeometry? bool inPlaneResampleExtentByGeometry = false; datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) { VtkResliceInterpolationProperty *resliceInterpolationProperty; datanode->GetProperty( resliceInterpolationProperty, "reslice interpolation" ); int interpolationMode = VTK_RESLICE_NEAREST; if ( resliceInterpolationProperty != NULL ) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } switch ( interpolationMode ) { case VTK_RESLICE_NEAREST: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); break; case VTK_RESLICE_LINEAR: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); break; case VTK_RESLICE_CUBIC: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); break; } } else { localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } //set the vtk output property to true, makes sure that no unneeded mitk image convertion //is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); //Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed { DataNode *dn=renderer->GetCurrentWorldPlaneGeometryNode(); if(dn) { ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=1; if(thickSlicesNum > 10) thickSlicesNum=10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); if(thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; if ( planeGeometry != NULL ){ normal = planeGeometry->GetNormal(); }else{ const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); if(abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else return; //no fitting geometry set } normal.Normalize(); input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); dataZSpacing = 1.0 / normInIndex.GetNorm(); localStorage->m_Reslicer->SetOutputDimensionality( 3 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); localStorage->m_TSFilter->SetInputData( localStorage->m_Reslicer->GetVtkOutput() ); //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually localStorage->m_Reslicer->Modified(); localStorage->m_Reslicer->Update(); localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { //this is needed when thick mode was enable bevore. These variable have to be reset to default values localStorage->m_Reslicer->SetOutputDimensionality( 2 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); localStorage->m_Reslicer->Modified(); //start the pipeline with updating the largest possible, needed if the geometry of the input has changed localStorage->m_Reslicer->UpdateLargestPossibleRegion(); localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } // Bounds information for reslicing (only reuqired if reference geometry // is present) //this used for generating a vtkPLaneSource with the right size double sliceBounds[6]; for ( int i = 0; i < 6; ++i ) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); //get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture { double textureClippingBounds[6]; for ( int i = 0; i < 6; ++i ) { textureClippingBounds[i] = 0.0; } // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds ); textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); //clipping bounds for cutting the image localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds); } //get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); //get the showIsoLines property bool showIsoLines = false; datanode->GetBoolProperty( "dose.showIsoLines", showIsoLines, renderer ); if(showIsoLines) //contour rendering { //generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) { if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { float binaryOutlineShadowWidth(1.5); datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); } localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); } } else { localStorage->m_ReslicedImage = NULL; localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); return; } this->ApplyOpacity( renderer ); this->ApplyRenderingMode(renderer); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); int displayedComponent = 0; if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1) { localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent); localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { //connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage); } // check for texture interpolation property bool textureInterpolation = false; GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); //set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); // connect the texture with the output of the levelwindow filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); this->TransformActor( renderer ); vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); if(showIsoLines) //connect the mapper with the polyData which contains the lines { //We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData); localStorage->m_Actor->SetTexture(NULL); //no texture for contours bool binaryOutlineShadow( false ); datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); if ( binaryOutlineShadow ) contourShadowActor->SetVisibility( true ); else contourShadowActor->SetVisibility( false ); } else { //Connect the mapper with the input texture. This is the standard case. //setup the textured plane this->GeneratePlane( renderer, sliceBounds ); //set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); //set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); contourShadowActor->SetVisibility( false ); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::DoseImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); LevelWindow levelWindow; this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); mitk::LevelWindow opacLevelWindow; if( this->GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) { //pass the opaque level window to the filter localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else { //no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } } void mitk::DoseImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); float rgb[3]= { 1.0f, 1.0f, 1.0f }; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); if(hover && !selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.hoveringcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor( rgb, renderer, "color" ); } } if(selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.selectedcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor(rgb, renderer, "color"); } } if(!hover && !selected) { GetDataNode()->GetColor( rgb, renderer, "color" ); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); localStorage->m_Actor->GetProperty()->SetColor(rgbConv); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { float rgb[3]= { 1.0f, 1.0f, 1.0f }; mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("outline binary shadow color", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv); } } void mitk::DoseImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists GetDataNode()->GetOpacity( opacity, renderer, "opacity" ); //set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); } } void mitk::DoseImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); if(binary) // is it a binary image? { //for binary images, we always use our default LuT and map every value to (0,1) //the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window. localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable); } else { //all other image types can make use of the rendering mode int renderingMode = mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR; mitk::RenderingModeProperty::Pointer mode = dynamic_cast(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer )); if(mode.IsNotNull()) { renderingMode = mode->GetRenderingMode(); } switch(renderingMode) { case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color"; this->ApplyLookuptable( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color"; this->ApplyLookuptable( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); break; default: MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead."; this->ApplyLookuptable( renderer ); this->ApplyLevelWindow( renderer ); break; } } //we apply color for all images (including binaries). this->ApplyColor( renderer ); } void mitk::DoseImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable; // If lookup table or transferfunction use is requested... mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); if( lookupTableProp.IsNotNull() ) // is a lookuptable set? { usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. //A default (rainbow) lookup table will be used. //Here have to do nothing. Warning for the user has been removed, due to unwanted console output //in every interation of the rendering. } localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable); } void mitk::DoseImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer) { mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); if( transferFunctionProp.IsNull() ) { MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image Rendering.Transfer Function'. Nothing will be done."; return; } LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); //pass the transfer function to our level window filter localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction()); } void mitk::DoseImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) { return; } mitk::Image* data = const_cast( this->GetInput() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::DoseImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), renderer, overwrite ); if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New(); node->AddProperty( "Image Rendering.Mode", renderingModeProperty); // Set default grayscale look-up table mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); mitkLut->SetType(mitk::LookupTable::GRAYSCALE); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) { // modality provided by DICOM or other reader if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE { // Set inverse grayscale look-up table mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); } // Otherwise do nothing - the default grayscale look-up table has already been set } bool isBinaryImage(false); if ( ! node->GetBoolProperty("binary", isBinaryImage) ) { // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); sliceSelector->SetSliceNr(image->GetDimension(2)/2); sliceSelector->SetTimeNr(image->GetDimension(3)/2); sliceSelector->SetChannelNr(image->GetDimension(4)/2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) { minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue) { // centralSlice is strange, lets look at all data minValue = image->GetStatistics()->GetScalarValueMin(); maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); } // some more properties specific for a binary... if (isBinaryImage) { node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } else //...or image type object { node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); std::string className = image->GetNameOfClass(); if (className != "TensorImage" && className != "QBallImage") { PixelType pixelType = image->GetPixelType(); size_t numComponents = pixelType.GetNumberOfComponents(); if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || numComponents > 4) node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite); } } if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; if ( image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowCenter", sLevel ) && image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) ) { float level = atof( sLevel.c_str() ); float window = atof( sWindow.c_str() ); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; if ( image->GetPropertyList()->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries ) && image->GetPropertyList()->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) ) { float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? // might remedy some l/w widget challenges } else { contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback } contrast.SetLevelWindow( level, window, true ); node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); } } if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) && (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) && (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) ) { mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->SetProperty( "opaclevelwindow", prop, renderer ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } mitk::DoseImageVtkMapper2D::LocalStorage* mitk::DoseImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } vtkSmartPointer mitk::DoseImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ) { vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(3); colors->SetName("Colors"); float pref; - this->GetDataNode()->GetFloatProperty(mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + this->GetDataNode()->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); - mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast(GetDataNode()->GetProperty(mitk::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast(GetDataNode()->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = propIsoSet->GetValue(); for(mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT!=isoDoseLevelSet->End();++doseIT) { if(doseIT->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, &(doseIT.Value()), pref, points, lines, colors); }//end of if visible dose value }//end of loop over all does values mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec = dynamic_cast(GetDataNode()->GetProperty(mitk::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelVector::Pointer frereIsoDoseLevelVec = propfreeIsoVec->GetValue(); for(mitk::IsoDoseLevelVector::ConstIterator freeDoseIT = frereIsoDoseLevelVec->Begin(); freeDoseIT!=frereIsoDoseLevelVec->End();++freeDoseIT) { if(freeDoseIT->Value()->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, freeDoseIT->Value(), pref, points, lines, colors); }//end of if visible dose value }//end of loop over all does values // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); polyData->GetCellData()->SetScalars(colors); return polyData; } void mitk::DoseImageVtkMapper2D::CreateLevelOutline(mitk::BaseRenderer* renderer, const mitk::IsoDoseLevel* level, float pref, vtkSmartPointer points, vtkSmartPointer lines, vtkSmartPointer colors) { LocalStorage* localStorage = this->GetLocalStorage(renderer); //get the min and max index values of each direction int* extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image int line = dims[0]; //how many pixels per line? //get the depth for each contour float depth = CalculateLayerDepth(renderer); double doseValue = level->GetDoseValue()*pref; mitk::IsoDoseLevel::ColorType isoColor = level->GetColor(); unsigned char colorLine[3] = {isoColor.GetRed()*255, isoColor.GetGreen()*255, isoColor.GetBlue()*255}; int x = xMin; //pixel index x int y = yMin; //pixel index y unsigned short* currentPixel; // We take the pointer to the first pixel of the image currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); while (y <= yMax) { //if the current pixel value is set to something if ((currentPixel) && (*currentPixel >= doseValue)) { //check in which direction a line is necessary //a line is added if the neighbor of the current pixel has the value 0 //and if the pixel is located at the edge of the image //if vvvvv not the first line vvvvv if (y > yMin && *(currentPixel-line) < doseValue) { //x direction - bottom edge of the pixel //add the 2 points vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); //add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv not the last line vvvvv if (y < yMax && *(currentPixel+line) < doseValue) { //x direction - top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv not the first pixel vvvvv if ( (x > xMin || y > yMin) && *(currentPixel-1) < doseValue) { //y direction - left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv not the last pixel vvvvv if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) < doseValue) { //y direction - right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } /* now consider pixels at the edge of the image */ //if vvvvv left edge of image vvvvv if (x == xMin) { //draw left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv right edge of image vvvvv if (x == xMax) { //draw right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv bottom edge of image vvvvv if (y == yMin) { //draw bottom edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } //if vvvvv top edge of image vvvvv if (y == yMax) { //draw top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); colors->InsertNextTupleValue(colorLine); } }//end if currentpixel is set x++; if (x > xMax) { //reached end of line x = xMin; y++; } // Increase the pointer-position to the next pixel. // This is safe, as the while-loop and the x-reset logic above makes // sure we do not exceed the bounds of the image currentPixel++; }//end of while } void mitk::DoseImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); //transform the origin to center based coordinates, because MITK is center based. localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); secondaryActor->SetUserTransform(trans); secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); } } bool mitk::DoseImageVtkMapper2D::RenderingGeometryIntersectsImage( const PlaneGeometry* renderingGeometry, SlicedGeometry3D* imageGeometry ) { // if either one of the two geometries is NULL we return true // for safety reasons if ( renderingGeometry == NULL || imageGeometry == NULL ) return true; // get the distance for the first cornerpoint ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) ); for( int i=1; i<8; i++ ) { mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); // get the distance to the other cornerpoints ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); // if it has not the same signing as the distance of the first point if ( initialDistance * distance < 0 ) { // we have an intersection and return true return true; } } // all distances have the same sign, no intersection and we return false return false; } mitk::DoseImageVtkMapper2D::LocalStorage::~LocalStorage() { } mitk::DoseImageVtkMapper2D::LocalStorage::LocalStorage() : m_VectorComponentExtractor(vtkSmartPointer::New()) { m_LevelWindowFilter = vtkSmartPointer::New(); //Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New().GetPointer(); m_DefaultLookupTable = vtkSmartPointer::New(); m_BinaryLookupTable = vtkSmartPointer::New(); m_ColorLookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actors = vtkSmartPointer::New(); m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); m_EmptyPolyData = vtkSmartPointer::New(); //the following actions are always the same and thus can be performed //in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); mitk::LookupTable::Pointer mitkLUT = mitk::LookupTable::New(); //built a default lookuptable mitkLUT->SetType(mitk::LookupTable::GRAYSCALE); m_DefaultLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY); m_BinaryLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_RAINBOW_COLOR); m_ColorLookupTable = mitkLUT->GetVtkLookupTable(); //do not repeat the texture (the image) m_Texture->RepeatOff(); //set the mapper for the actor m_Actor->SetMapper( m_Mapper ); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); outlineShadowActor->SetMapper( m_Mapper ); m_Actors->AddPart( outlineShadowActor ); m_Actors->AddPart( m_Actor ); } diff --git a/Modules/DicomRT/src/mitkRTConstants.cpp b/Modules/DicomRT/src/mitkRTConstants.cpp index 1dfd7b57d0..cfa34e44fd 100644 --- a/Modules/DicomRT/src/mitkRTConstants.cpp +++ b/Modules/DicomRT/src/mitkRTConstants.cpp @@ -1,28 +1,28 @@ /*=================================================================== 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 "mitkRTConstants.h" -const std::string mitk::Constants::DOSE_PROPERTY_NAME = "dose"; -const std::string mitk::Constants::PRESCRIBED_DOSE_PROPERTY_NAME = "dose.PrescribedDose"; -const std::string mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME = "dose.ReferenceDose"; -const std::string mitk::Constants::DOSE_TYPE_PROPERTY_NAME = "dose.type"; -const std::string mitk::Constants::DOSE_SUMMATION_TYPE_PROPERTY_NAME = "dose.summationType"; -const std::string mitk::Constants::DOSE_FRACTION_COUNT_PROPERTY_NAME = "dose.fractionCount"; -const std::string mitk::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME = "dose.showIsoLines"; -const std::string mitk::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME = "dose.showColorWash"; -const std::string mitk::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME = "dose.isoLevels"; -const std::string mitk::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME = "dose.freeIsoValues"; +const std::string mitk::RTConstants::DOSE_PROPERTY_NAME = "dose"; +const std::string mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME = "dose.PrescribedDose"; +const std::string mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME = "dose.ReferenceDose"; +const std::string mitk::RTConstants::DOSE_TYPE_PROPERTY_NAME = "dose.type"; +const std::string mitk::RTConstants::DOSE_SUMMATION_TYPE_PROPERTY_NAME = "dose.summationType"; +const std::string mitk::RTConstants::DOSE_FRACTION_COUNT_PROPERTY_NAME = "dose.fractionCount"; +const std::string mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME = "dose.showIsoLines"; +const std::string mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME = "dose.showColorWash"; +const std::string mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME = "dose.isoLevels"; +const std::string mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME = "dose.freeIsoValues"; diff --git a/Modules/DicomRT/src/mitkRTDoseReader.cpp b/Modules/DicomRT/src/mitkRTDoseReader.cpp index aacfc367d3..e7cd45d90c 100644 --- a/Modules/DicomRT/src/mitkRTDoseReader.cpp +++ b/Modules/DicomRT/src/mitkRTDoseReader.cpp @@ -1,144 +1,144 @@ /*=================================================================== 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 "mitkRTDoseReader.h" #include #include #include #include #include #include namespace mitk { RTDoseReader::RTDoseReader(){} RTDoseReader::~RTDoseReader(){} mitk::DataNode::Pointer RTDoseReader:: LoadRTDose(const char* filename) { DcmFileFormat fileformat; OFCondition outp = fileformat.loadFile(filename, EXS_Unknown); if(outp.bad()) { MITK_ERROR << "Cant read the file" << std::endl; } DcmDataset *dataset = fileformat.getDataset(); std::string name = filename; itk::FilenamesContainer file; file.push_back(name); mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader; mitk::DataNode::Pointer originalNode = reader->LoadDicomSeries(file,false); if(originalNode.IsNull()) { MITK_ERROR << "Error reading the dcm file" << std::endl; return 0; } mitk::Image::Pointer originalImage = dynamic_cast(originalNode->GetData()); DRTDoseIOD doseObject; OFCondition result = doseObject.read(*dataset); if(result.bad()) { MITK_ERROR << "Error reading the Dataset" << std::endl; return 0; } OFString gridScaling; Float32 gridscale; doseObject.getDoseGridScaling(gridScaling); gridscale = OFStandard::atof(gridScaling.c_str()); AccessByItk_1(originalImage, MultiplayGridScaling, gridscale); double prescripeDose = this->GetMaxDoseValue(dataset); originalNode->SetName("RT Dose"); - originalNode->SetFloatProperty(mitk::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescripeDose); - originalNode->SetFloatProperty(mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40); - originalNode->SetBoolProperty(mitk::Constants::DOSE_PROPERTY_NAME.c_str(),true); + originalNode->SetFloatProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescripeDose); + originalNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40); + originalNode->SetBoolProperty(mitk::RTConstants::DOSE_PROPERTY_NAME.c_str(),true); return originalNode; } template void RTDoseReader::MultiplayGridScaling(itk::Image* image, Float32 gridscale) { typedef itk::Image InputImageType; itk::ImageRegionIterator it(image, image->GetRequestedRegion()); for(it=it.Begin(); !it.IsAtEnd(); ++it) { it.Set(it.Get()*gridscale); } } double RTDoseReader::GetMaxDoseValue(DcmDataset* dataSet) { DRTDoseIOD doseObject; OFCondition result = doseObject.read(*dataSet); if(result.bad()) { MITK_ERROR << "Error reading the RT Dose dataset" << std::endl; return 0; } Uint16 rows, columns, frames; OFString nrframes, gridScaling; const Uint16 *pixelData = NULL; Float32 gridscale; Uint16 &rows_ref = rows; Uint16 &columns_ref = columns; doseObject.getRows(rows_ref); doseObject.getColumns(columns_ref); doseObject.getNumberOfFrames(nrframes); doseObject.getDoseGridScaling(gridScaling); frames = atoi(nrframes.c_str()); gridscale = OFStandard::atof(gridScaling.c_str()); dataSet->findAndGetUint16Array(DCM_PixelData, pixelData, 0); int size = columns*rows*frames; double highest = 0; for(int i=0; ihighest) { highest = pixelData[i] * gridscale; } } return highest; } } diff --git a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp b/Modules/DicomRT/src/mitkRTStructureSetReader.cpp index cda808bfc9..c2315a6650 100644 --- a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp +++ b/Modules/DicomRT/src/mitkRTStructureSetReader.cpp @@ -1,248 +1,242 @@ /*=================================================================== 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 "mitkRTStructureSetReader.h" #include #include namespace mitk { RTStructureSetReader::RTStructureSetReader(){} RTStructureSetReader::~RTStructureSetReader(){} RTStructureSetReader::RoiEntry::RoiEntry() { Number = 0; DisplayColor[0]=1.0; DisplayColor[1]=0.0; DisplayColor[2]=0.0; ContourModelSet=mitk::ContourModelSet::New(); } RTStructureSetReader::RoiEntry::RoiEntry(const RoiEntry &src) { Number=src.Number; Name=src.Name; Description=src.Description; DisplayColor[0]=src.DisplayColor[0]; DisplayColor[1]=src.DisplayColor[1]; DisplayColor[2]=src.DisplayColor[2]; ContourModelSet=mitk::ContourModelSet::New(); SetPolyData(src.ContourModelSet); } RTStructureSetReader::RoiEntry::~RoiEntry(){} RTStructureSetReader::RoiEntry& RTStructureSetReader:: RoiEntry::operator =(const RoiEntry &src) { Number=src.Number; Name=src.Name; Description=src.Description; DisplayColor[0]=src.DisplayColor[0]; DisplayColor[1]=src.DisplayColor[1]; DisplayColor[2]=src.DisplayColor[2]; SetPolyData(src.ContourModelSet); return (*this); } void RTStructureSetReader::RoiEntry:: SetPolyData(mitk::ContourModelSet::Pointer roiPolyData) { if (roiPolyData == this->ContourModelSet) return; this->ContourModelSet = roiPolyData; } size_t RTStructureSetReader::GetNumberOfROIs() { return this->ROISequenceVector.size(); } RTStructureSetReader::RoiEntry* RTStructureSetReader:: FindRoiByNumber(unsigned int roiNum) { for(unsigned int i=0; iROISequenceVector.size(); ++i) { if(this->ROISequenceVector[i].Number == roiNum) return &this->ROISequenceVector[i]; } return NULL; } RTStructureSetReader::ContourModelSetNodes RTStructureSetReader:: ReadStructureSet(const char* filepath) { DcmFileFormat file; OFCondition output = file.loadFile(filepath, EXS_Unknown); if(output.bad()) { MITK_ERROR << "Cant read the file" << std::endl; } DcmDataset *dataset = file.getDataset(); DRTStructureSetIOD structureSetObject; OFCondition outp = structureSetObject.read(*dataset); if(!outp.good()) { MITK_ERROR << "Error reading the file" << std::endl; RTStructureSetReader::ContourModelSetNodes x; return x; } DRTStructureSetROISequence &roiSequence = structureSetObject.getStructureSetROISequence(); if(!roiSequence.gotoFirstItem().good()) { MITK_ERROR << "Error reading the structure sequence" << std::endl; RTStructureSetReader::ContourModelSetNodes x; return x; } do{ DRTStructureSetROISequence::Item ¤tSequence = roiSequence.getCurrentItem(); if(!currentSequence.isValid()) { continue; } OFString roiName; OFString roiDescription; Sint32 roiNumber; RoiEntry roi; currentSequence.getROIName(roiName); currentSequence.getROIDescription(roiDescription); currentSequence.getROINumber(roiNumber); roi.Name = roiName.c_str(); roi.Description = roiDescription.c_str(); roi.Number = roiNumber; this->ROISequenceVector.push_back(roi); } while(roiSequence.gotoNextItem().good()); Sint32 refRoiNumber; DRTROIContourSequence &roiContourSeqObject = structureSetObject.getROIContourSequence(); if(!roiContourSeqObject.gotoFirstItem().good()) { MITK_ERROR << "Error reading the contour sequence" << std::endl; RTStructureSetReader::ContourModelSetNodes x; return x; } do { mitk::ContourModelSet::Pointer contourSet = mitk::ContourModelSet::New(); DRTROIContourSequence::Item ¤tRoiObject = roiContourSeqObject.getCurrentItem(); if(!currentRoiObject.isValid()) { continue; } currentRoiObject.getReferencedROINumber(refRoiNumber); DRTContourSequence &contourSeqObject = currentRoiObject.getContourSequence(); if(contourSeqObject.gotoFirstItem().good()) { do { DRTContourSequence::Item &contourItem = contourSeqObject.getCurrentItem(); if(!contourItem.isValid()) { continue; } OFString contourNumber; OFString numberOfPoints; OFVector contourData_LPS; mitk::ContourModel::Pointer contourSequence = mitk::ContourModel::New(); contourItem.getContourNumber(contourNumber); contourItem.getNumberOfContourPoints(numberOfPoints); contourItem.getContourData(contourData_LPS); for(unsigned int i=0; iAddVertex(point); } contourSequence->Close(); contourSet->AddContourModel(contourSequence); } while(contourSeqObject.gotoNextItem().good()); } else { MITK_ERROR << "Error reading contourSeqObject" << std::endl; } RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); if(refROI==NULL) { MITK_ERROR << "Can not find references ROI" << std::endl; continue; } Sint32 roiColor; for(int j=0;j<3;j++) { currentRoiObject.getROIDisplayColor(roiColor, j); refROI->DisplayColor[j] = roiColor/255.0; } refROI->ContourModelSet = contourSet; contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); contourSet->SetProperty("contour.color", mitk::ColorProperty::New( refROI->DisplayColor[0], refROI->DisplayColor[1], refROI->DisplayColor[2])); + contourModelSetVector.push_back(contourSet); } while(roiContourSeqObject.gotoNextItem().good()); std::deque nodes; for(unsigned int i=0; iSetData(ROISequenceVector.at(i).ContourModelSet); - node->SetProperty("name", - ROISequenceVector.at(i).ContourModelSet->GetProperty("name")); - node->SetProperty("color", - ROISequenceVector.at(i).ContourModelSet->GetProperty("contour.color")); - node->SetProperty("contour.color", - ROISequenceVector.at(i).ContourModelSet->GetProperty("contour.color")); - - /*The StructureSets should only be visible in the axial-view and the - 3D-view because in the other views they are just points and lines*/ - node->SetVisibility(true, mitk::BaseRenderer::GetInstance - ( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); - node->SetVisibility(false, mitk::BaseRenderer::GetInstance - ( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); - node->SetVisibility(false, mitk::BaseRenderer::GetInstance - ( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); - node->SetVisibility(true, mitk::BaseRenderer::GetInstance - ( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + + node->SetData(contourModelSetVector.at(i)); + node->SetProperty("name", contourModelSetVector.at(i)->GetProperty("name")); + node->SetProperty("color",contourModelSetVector.at(i)->GetProperty("contour.color")); + node->SetProperty("contour.color",contourModelSetVector.at(i)->GetProperty("contour.color")); + node->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); + node->SetVisibility(true, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); + node->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); + node->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); + node->SetVisibility(true, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + nodes.push_back(node); } return nodes; } } diff --git a/Modules/DicomUI/src/QmitkDicomExternalDataWidget.cpp b/Modules/DicomUI/src/QmitkDicomExternalDataWidget.cpp index 8c3f2eb636..c5b9888526 100644 --- a/Modules/DicomUI/src/QmitkDicomExternalDataWidget.cpp +++ b/Modules/DicomUI/src/QmitkDicomExternalDataWidget.cpp @@ -1,210 +1,215 @@ /*=================================================================== 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. ===================================================================*/ // Qmitk #include "QmitkDicomExternalDataWidget.h" #include // CTK #include // Qt #include #include const std::string QmitkDicomExternalDataWidget::Widget_ID = "org.mitk.Widgets.QmitkDicomExternalDataWidget"; QmitkDicomExternalDataWidget::QmitkDicomExternalDataWidget(QWidget *parent) : QWidget(parent) , m_Controls (0) { Initialize(); CreateQtPartControl(this); } QmitkDicomExternalDataWidget::~QmitkDicomExternalDataWidget() { } void QmitkDicomExternalDataWidget::CreateQtPartControl( QWidget *parent ) { // build up qt Widget, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkDicomExternalDataWidgetControls; m_Controls->setupUi( parent ); m_Controls->viewExternalDataButton->setVisible(true); m_Controls->ctkDICOMBrowser->setTableOrientation(Qt::Vertical); m_Controls->ctkDICOMBrowser->setDICOMDatabase(m_ExternalDatabase); this->SetupImportDialog(); this->SetupProgressDialog(parent); //connect Buttons connect(m_Controls->downloadButton, SIGNAL(clicked()),this,SLOT(OnDownloadButtonClicked())); connect(m_Controls->viewExternalDataButton, SIGNAL(clicked()),this,SLOT(OnViewButtonClicked())); connect(m_Controls->directoryButton, SIGNAL(clicked()), this, SLOT(OnScanDirectory())); connect(m_Controls->ctkDICOMBrowser, SIGNAL(seriesSelectionChanged(const QStringList&)), this, SLOT(OnSeriesSelectionChanged(const QStringList&))); connect(m_Controls->ctkDICOMBrowser, SIGNAL(seriesDoubleClicked(const QModelIndex&)), this, SLOT(OnViewButtonClicked())); connect(m_ProgressDialog, SIGNAL(canceled()), m_ExternalIndexer, SLOT(cancel())); connect(m_ExternalIndexer, SIGNAL(indexingComplete()),this, SLOT(OnFinishedImport())); connect(m_ExternalIndexer, SIGNAL(indexingFilePath(const QString&)), m_ProgressDialogLabel, SLOT(setText(const QString&))); connect(m_ExternalIndexer, SIGNAL(progress(int)), m_ProgressDialog, SLOT(setValue(int))); } } void QmitkDicomExternalDataWidget::Initialize() { m_ExternalDatabase = new ctkDICOMDatabase(this); try{ m_ExternalDatabase->openDatabase(QString(":memory:"),QString( "EXTERNAL-DB")); }catch(std::exception e){ MITK_ERROR <<"Database error: "<< m_ExternalDatabase->lastError().toStdString(); m_ExternalDatabase->closeDatabase(); return; } m_ExternalIndexer = new ctkDICOMIndexer(this); } void QmitkDicomExternalDataWidget::OnFinishedImport() { m_ProgressDialog->setValue(m_ProgressDialog->maximum()); } void QmitkDicomExternalDataWidget::OnDownloadButtonClicked() { QStringList filesToDownload = GetFileNamesFromIndex(); if (filesToDownload.size() == 0) { QMessageBox info; info.setText("You have to select an entry in the dicom browser for import."); info.exec(); return; } emit SignalStartDicomImport(GetFileNamesFromIndex()); } void QmitkDicomExternalDataWidget::OnViewButtonClicked() { QStringList uids = m_Controls->ctkDICOMBrowser->currentSeriesSelection(); QString uid; foreach (uid, uids) { QStringList filesForSeries = m_ExternalDatabase->filesForSeries(uid); QHash eventProperty; eventProperty.insert("FilesForSeries", filesForSeries); + if(!filesForSeries.isEmpty()) + { + QString modality = m_ExternalDatabase->fileValue(filesForSeries.at(0),"0008,0060"); + eventProperty.insert("Modality", modality); + } emit SignalDicomToDataManager(eventProperty); } } QStringList QmitkDicomExternalDataWidget::GetFileNamesFromIndex() { QStringList filePaths; QString uid; QStringList seriesUIDs = m_Controls->ctkDICOMBrowser->currentSeriesSelection(); foreach (uid, seriesUIDs) { filePaths.append(m_ExternalDatabase->filesForSeries(uid)); } if (!filePaths.empty()) return filePaths; QStringList studyUIDs = m_Controls->ctkDICOMBrowser->currentStudiesSelection(); foreach (uid, studyUIDs) { seriesUIDs = m_ExternalDatabase->seriesForStudy(uid); foreach (uid, seriesUIDs) { filePaths.append(m_ExternalDatabase->filesForSeries(uid)); } } if (!filePaths.empty()) return filePaths; QStringList patientsUIDs = m_Controls->ctkDICOMBrowser->currentPatientsSelection(); foreach (uid, patientsUIDs) { studyUIDs = m_ExternalDatabase->studiesForPatient(uid); foreach (uid, studyUIDs) { seriesUIDs = m_ExternalDatabase->seriesForStudy(uid); foreach (uid, seriesUIDs) { filePaths.append(m_ExternalDatabase->filesForSeries(uid)); } } } return filePaths; } void QmitkDicomExternalDataWidget::OnStartDicomImport(const QString& directory) { m_ImportDialog->close(); m_ProgressDialog->show(); m_LastImportDirectory = directory; m_ExternalIndexer->addDirectory(*m_ExternalDatabase,m_LastImportDirectory); } void QmitkDicomExternalDataWidget::OnSeriesSelectionChanged(const QStringList& s) { m_Controls->viewExternalDataButton->setEnabled( (s.size() != 0) ); } void QmitkDicomExternalDataWidget::SetupImportDialog() { //Initialize import widget m_ImportDialog = new ctkFileDialog(this); // Since copy on import is not working at the moment // this feature is diabled // QCheckBox* importCheckbox = new QCheckBox("Copy on import", m_ImportDialog); // m_ImportDialog->setBottomWidget(importCheckbox); m_ImportDialog->setFileMode(QFileDialog::Directory); m_ImportDialog->setLabelText(QFileDialog::Accept,"Import"); m_ImportDialog->setWindowTitle("Import DICOM files from directory ..."); m_ImportDialog->setWindowModality(Qt::ApplicationModal); connect(m_ImportDialog, SIGNAL(fileSelected(QString)),this,SLOT(OnStartDicomImport(QString))); } void QmitkDicomExternalDataWidget::SetupProgressDialog(QWidget* parent) { m_ProgressDialog = new QProgressDialog("DICOM Import", "Cancel", 0, 100, parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint); m_ProgressDialogLabel = new QLabel("Initialization...", m_ProgressDialog); m_ProgressDialog->setLabel(m_ProgressDialogLabel); m_ProgressDialog->setWindowModality(Qt::ApplicationModal); m_ProgressDialog->setMinimumDuration(0); } void QmitkDicomExternalDataWidget::OnScanDirectory() { m_ImportDialog->show(); } diff --git a/Modules/RTUI/CMakeLists.txt b/Modules/RTUI/CMakeLists.txt new file mode 100644 index 0000000000..4c3873ac17 --- /dev/null +++ b/Modules/RTUI/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE( + INCLUDE_DIRS Qmitk Helper + DEPENDS MitkDicomRT MitkQtWidgets MitkQtWidgetsExt + PACKAGE_DEPENDS CTK Qt4|Qtcore +) diff --git a/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp new file mode 100644 index 0000000000..8496c1cb47 --- /dev/null +++ b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp @@ -0,0 +1,134 @@ +/*=================================================================== + +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 "mitkIsoLevelsGenerator.h" + +mitk::IsoDoseLevelSet::Pointer mitk::GeneratIsoLevels_Virtuos() +{ + mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); + + mitk::IsoDoseLevel::ColorType color; + color[0] = 0.0; + color[1] = 0.0; + color[2] = 0.4; + mitk::IsoDoseLevel::Pointer level = mitk::IsoDoseLevel::New(0.01,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.2; + color[2] = 0.8; + level = mitk::IsoDoseLevel::New(0.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.4; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 1.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(0.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.6,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.7,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.8; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.8,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.5; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.9,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.95,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.2; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(1.0,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(1.07,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.7; + color[2] = 0.7; + level = mitk::IsoDoseLevel::New(1.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.8; + color[1] = 0.6; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(1.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.65; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + return levelSet; +} diff --git a/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h new file mode 100644 index 0000000000..9631246478 --- /dev/null +++ b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h @@ -0,0 +1,30 @@ +/*=================================================================== + +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 __ISO_LEVELS_GENERATOR_H +#define __ISO_LEVELS_GENERATOR_H + +#include "mitkIsoDoseLevelCollections.h" + +#include "MitkRTUIExports.h" + +namespace mitk +{ +IsoDoseLevelSet::Pointer MitkRTUI_EXPORT GeneratIsoLevels_Virtuos(); +} + +#endif diff --git a/Modules/RTUI/Helper/mitkRTUIConstants.cpp b/Modules/RTUI/Helper/mitkRTUIConstants.cpp new file mode 100644 index 0000000000..fcb00705ef --- /dev/null +++ b/Modules/RTUI/Helper/mitkRTUIConstants.cpp @@ -0,0 +1,45 @@ +/*=================================================================== + +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 "mitkRTUIConstants.h" + +const std::string mitk::RTUIConstants::ROOT_PREFERENCE_NODE_ID = "/RT/UI"; +const std::string mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID = "unkownDoseHandlingStyle"; +const std::string mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID = "unkownDoseHandlingValue"; + + +const std::string mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID = "/RT/UI/doseVis"; +const std::string mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID = "/RT/UI/doseVis/isoPresets"; +const std::string mitk::RTUIConstants::REFERENCE_DOSE_ID = "referenceDose"; +const std::string mitk::RTUIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID = "globalReferenceDoseSync"; +const std::string mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID = "doseDisplayAbsolute"; +const std::string mitk::RTUIConstants::GLOBAL_VISIBILITY_ISOLINES_ID = "globalVisibilityIsoLines"; +const std::string mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID = "globalVisibilityColorWash"; +const std::string mitk::RTUIConstants::SELECTED_ISO_PRESET_ID = "selectedIsoPreset"; + +const std::string mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID = "doseValue"; +const std::string mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID = "color_R"; +const std::string mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID = "color_G"; +const std::string mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID = "color_B"; +const std::string mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID = "visibleIsoLines"; +const std::string mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID = "visibleColorWash"; + +const mitk::DoseValueAbs mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE = 40.0; + +const std::string mitk::RTCTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS = "org/mitk/rt/dosevisualization/presets"; +const std::string mitk::RTCTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED = "org/mitk/rt/dosevisualization/presets/CHANGED"; +const std::string mitk::RTCTKEventConstants::TOPIC_REFERENCE_DOSE = "org/mitk/rt/dosevisualization/referenceDose"; +const std::string mitk::RTCTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED = "org/mitk/rt/dosevisualization/referenceDose/CHANGED"; diff --git a/Modules/RTUI/Helper/mitkRTUIConstants.h b/Modules/RTUI/Helper/mitkRTUIConstants.h new file mode 100644 index 0000000000..d59f1e1a5f --- /dev/null +++ b/Modules/RTUI/Helper/mitkRTUIConstants.h @@ -0,0 +1,83 @@ +/*=================================================================== + +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 _MITK_RT_UI_CONSTANTS_H_ +#define _MITK_RT_UI_CONSTANTS_H_ + +#include +#include + +#include "MitkRTUIExports.h" + +namespace mitk +{ +struct MitkRTUI_EXPORT RTUIConstants +{ + /** ID/Path of main preference node for RT UI. */ + static const std::string ROOT_PREFERENCE_NODE_ID; + /** Bool that indicates how the prescribed dose should be defined, if unkown. True: UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE should be used as + default dose value in Gy; False: it should be used as fraction of the max dose to determin the prescribed dose.*/ + static const std::string UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID; + /** Value that is used to determin unknown prescribed doses.*/ + static const std::string UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID; + + /** ID/Path of main preference node where all iso dose level presets are stored (e.g. ROOT_ISO_PRESETS_PREFERENCE_NODE_ID+"/[Preset1]"). */ + static const std::string ROOT_ISO_PRESETS_PREFERENCE_NODE_ID; + /** ID/Path of main preference for dose visualization preferences. */ + static const std::string ROOT_DOSE_VIS_PREFERENCE_NODE_ID; + /** ID for the reference dose stored as preference. */ + static const std::string REFERENCE_DOSE_ID; + /** ID for the preference flag that indicates if the reference dose is synced for all nodes*/ + static const std::string GLOBAL_REFERENCE_DOSE_SYNC_ID; + /** ID for the flag if dose should be displayed as absoulte dose. */ + static const std::string DOSE_DISPLAY_ABSOLUTE_ID; + /** ID for the global visiblity switch for iso line visualization. */ + static const std::string GLOBAL_VISIBILITY_ISOLINES_ID; + /** ID for the global visiblity switch for color wash visualization. */ + static const std::string GLOBAL_VISIBILITY_COLORWASH_ID; + /** ID for the selected iso preset that should be used (value of ROOT_ISO_PRESETS_PREFERENCE_NODE_ID + value of this key can + be used to construct the passed to the selected preset. */ + static const std::string SELECTED_ISO_PRESET_ID; + + /** ID for the relative dose value of an iso dose level. */ + static const std::string ISO_LEVEL_DOSE_VALUE_ID; + /** ID for the color (red component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_RED_ID; + /** ID for the color (green component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_GREEN_ID; + /** ID for the color (blue component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_BLUE_ID; + /** ID for the visiblity switch for iso line visualization. */ + static const std::string ISO_LEVEL_VISIBILITY_ISOLINES_ID; + /** ID for the visiblity switch for color wash visualization. */ + static const std::string ISO_LEVEL_VISIBILITY_COLORWASH_ID; + + /** Default value used as reference_dose_if not defined by application or data node*/ + static const DoseValueAbs DEFAULT_REFERENCE_DOSE_VALUE; +}; + +struct MitkRTUI_EXPORT RTCTKEventConstants +{ + /** ID/Path of main preference node for RT UI. */ + static const std::string TOPIC_REFERENCE_DOSE; + static const std::string TOPIC_REFERENCE_DOSE_CHANGED; + static const std::string TOPIC_ISO_DOSE_LEVEL_PRESETS; + static const std::string TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED; +}; + +} + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp new file mode 100644 index 0000000000..548b5cde00 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp @@ -0,0 +1,83 @@ +/*=================================================================== + +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 "QmitkDoseColorDelegate.h" + +#include +#include +#include +#include +#include +#include + +QmitkDoseColorDelegate::QmitkDoseColorDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.canConvert()) + { + QColor color = data.value(); + + painter->fillRect(option.rect, color); + } + else + { + QStyledItemDelegate::paint(painter, option, index); + } +} + +bool QmitkDoseColorDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + Q_ASSERT(event); + Q_ASSERT(model); + + // make sure that the item is checkable + Qt::ItemFlags flags = model->flags(index); + if (!(flags & Qt::ItemIsEditable) || !(flags & Qt::ItemIsEnabled)) + { + return false; + } + + // make sure that we have the right event type + QMouseEvent* mouseEvent = dynamic_cast(event); + if (!mouseEvent) + { + return false; + } + else + { + if (mouseEvent->type() != QEvent::MouseButtonRelease || mouseEvent->button() != Qt::LeftButton) + { + return false; + } + } + + QColor oldcolor = index.data(Qt::EditRole).value(); + QColor newColor = QColorDialog::getColor(oldcolor, NULL); + + if (newColor.isValid()) + { + return model->setData(index, QVariant(newColor), Qt::EditRole); + } + + return false; +}; diff --git a/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.h new file mode 100644 index 0000000000..78f027f81b --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.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 QmitkDoseColorDelegate_h +#define QmitkDoseColorDelegate_h + + +#include + +#include "MitkRTUIExports.h" + +/** \class QmitkDoseColorDelegate +\brief An item delegate for rendering and editing dose color in a QTableView.*/ +class MitkRTUI_EXPORT QmitkDoseColorDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + /// + /// Creates a new PropertyDelegate. + /// + QmitkDoseColorDelegate(QObject *parent = 0); + + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; +}; + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp new file mode 100644 index 0000000000..34ed4b28eb --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp @@ -0,0 +1,113 @@ +/*=================================================================== + +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 "QmitkDoseValueDelegate.h" + +#include +#include +#include +#include + +QmitkDoseValueDelegate::QmitkDoseValueDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::DisplayRole); + + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + + QStyle *style = QApplication::style(); + + + style->drawItemText(painter, opt.rect.adjusted(0,0,-5,0), Qt::AlignRight | Qt::AlignVCenter, opt.palette,true, data.toString()); +} + +QWidget* QmitkDoseValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + QVariant displayData = index.data(Qt::DisplayRole); + QVariant absoluteDose = index.data(Qt::UserRole+1); + + if(data.isValid()) + { + QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); + spinBox->setDecimals(2); + if (absoluteDose.toBool()) + { + spinBox->setSingleStep(0.5); + spinBox->setSuffix(QString(" Gy")); + } + else + { + spinBox->setSingleStep(1.0); + spinBox->setSuffix(QString(" %")); + } + + spinBox->setMinimum(0.0); + spinBox->setMaximum(9999.0); + + spinBox->installEventFilter( const_cast(this) ); + + return spinBox; + + } + else + return new QLabel(displayData.toString(), parent); + +} + +void QmitkDoseValueDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if(data.isValid()) + { + + QDoubleSpinBox* spinBox = qobject_cast(editor); + if (spinBox) + { + spinBox->setValue(data.toDouble()); + } + else + { + QStyledItemDelegate::setEditorData(editor, index); + } + } +} + +void QmitkDoseValueDelegate::setModelData(QWidget *editor, QAbstractItemModel* model + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if(data.isValid()) + { + QDoubleSpinBox* spinBox = qobject_cast(editor); + double doubleValue = spinBox->value(); + + QVariant doubleValueVariant(doubleValue); + model->setData(index, doubleValueVariant); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} diff --git a/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h new file mode 100644 index 0000000000..5116d84c62 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h @@ -0,0 +1,63 @@ +/*=================================================================== + +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 QmitkDoseValueDelegate_h +#define QmitkDoseValueDelegate_h + + +#include + +#include "MitkRTUIExports.h" + +/** \class QmitkDoseValueDelegate +\brief An item delegate for rendering and editing dose values. +The delegate assumes that the model uses the role Qt::UserRole+1 +to indicate if the returned dose value is an absolute (data(Qt::UserRole+1) == true) +or an relative dose (data(Qt::UserRole+1) == false).*/ +class MitkRTUI_EXPORT QmitkDoseValueDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + /// + /// Creates a new PropertyDelegate. + /// + QmitkDoseValueDelegate(QObject *parent = 0); + + /// + /// Renders a specific property (overwritten from QItemDelegate) + /// + void paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + /// + /// Create an editor for a specific property (overwritten from QItemDelegate) + /// + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + /// + /// Create an editor for a specific property (overwritten from QItemDelegate) + /// + void setEditorData(QWidget *editor, const QModelIndex &index) const; + + /// + /// When the user accepts input this func commits the data to the model (overwritten from QItemDelegate) + /// + void setModelData(QWidget *editor, QAbstractItemModel* model, const QModelIndex &index) const; +}; + +#endif /* QMITKPROPERTIESTABLEMODEL_H_ */ diff --git a/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp new file mode 100644 index 0000000000..9de4f0b4c8 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp @@ -0,0 +1,94 @@ +/*=================================================================== + +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 "QmitkDoseVisualStyleDelegate.h" + +#include +#include +#include +#include +#include + +static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) { + QStyleOptionButton check_box_style_option; + QRect check_box_rect = QApplication::style()->subElementRect( + QStyle::SE_CheckBoxIndicator, + &check_box_style_option); + QPoint check_box_point(view_item_style_options.rect.x() + + view_item_style_options.rect.width() / 2 - + check_box_rect.width() / 2, + view_item_style_options.rect.y() + + view_item_style_options.rect.height() / 2 - + check_box_rect.height() / 2); + return QRect(check_box_point, check_box_rect.size()); +} + +QmitkDoseVisualStyleDelegate::QmitkDoseVisualStyleDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseVisualStyleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + bool checkValue = index.data(Qt::DisplayRole).toBool(); + + QStyleOptionButton BtnStyle; + BtnStyle.state = QStyle::State_Enabled; + + if(checkValue) + { + BtnStyle.state |= QStyle::State_On; + } + else + { + BtnStyle.state |= QStyle::State_Off; + } + + BtnStyle.direction = QApplication::layoutDirection(); + BtnStyle.rect = CheckBoxRect(option); + QApplication::style()->drawControl(QStyle::CE_CheckBox,&BtnStyle,painter ); +} + +bool QmitkDoseVisualStyleDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + Q_ASSERT(event); + Q_ASSERT(model); + + // make sure that the item is checkable + Qt::ItemFlags flags = model->flags(index); + if (!(flags & Qt::ItemIsEditable) || !(flags & Qt::ItemIsEnabled)) + { + return false; + } + + // make sure that we have the right event type + QMouseEvent* mouseEvent = dynamic_cast(event); + if (!mouseEvent) + { + return false; + } + else + { + if (mouseEvent->type() != QEvent::MouseButtonRelease || mouseEvent->button() != Qt::LeftButton) + { + return false; + } + } + + bool newState = !(index.data(Qt::EditRole).toBool()); + + return model->setData(index, QVariant(newState), Qt::EditRole); +}; diff --git a/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h new file mode 100644 index 0000000000..7032fd11d0 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h @@ -0,0 +1,47 @@ +/*=================================================================== + +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 QmitkDoseVisualStyleDelegate_h +#define QmitkDoseVisualStyleDelegate_h + + +/// Toolkit includes. +#include + +#include "MitkRTUIExports.h" + + +/** \class QmitkDoseVisualStyleDelegate +\brief An item delegate for rendering and editing dose visualization options. +The delegate is used to handle aspects of a isodose level like visualization +of the isodose lines or colorwash display.*/ +class MitkRTUI_EXPORT QmitkDoseVisualStyleDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkDoseVisualStyleDelegate(QObject *parent = 0); + + void paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index); + +}; + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp new file mode 100644 index 0000000000..0a313dbedd --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp @@ -0,0 +1,145 @@ +/*=================================================================== + +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 "QmitkFreeIsoDoseLevelWidget.h" + + +QmitkFreeIsoDoseLevelWidget::QmitkFreeIsoDoseLevelWidget(QWidget*): m_ReferenceDose (40.0), m_InternalUpdate(false) +{ + this->setupUi(this); + + this->colorBtn->setDisplayColorName(false); + this->m_IsoDoseLevel = mitk::IsoDoseLevel::New(); + + connect(this->sbAbsValue, SIGNAL(valueChanged(double)), this, SLOT(OnAbsValueChanged(double))); + connect(this->sbRelValue, SIGNAL(valueChanged(double)), this, SLOT(OnRelValueChanged(double))); + connect(this->doseSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderChanged(int))); + connect(this->checkVisibleIso, SIGNAL(clicked(bool)), this, SLOT(OnVisibleClicked(bool))); + connect(this->colorBtn, SIGNAL(colorChanged(QColor)), this, SLOT(OnColorChanged(QColor))); +} + +mitk::DoseValueAbs + QmitkFreeIsoDoseLevelWidget:: + getReferenceDose() const +{ + return this->m_ReferenceDose; +}; + +mitk::IsoDoseLevel* + QmitkFreeIsoDoseLevelWidget:: + getIsoDoseLevel() const +{ + return this->m_IsoDoseLevel; +}; + +void QmitkFreeIsoDoseLevelWidget:: + setReferenceDose(double newReferenceDose) +{ + if (newReferenceDose != m_ReferenceDose) + { + this->m_ReferenceDose = newReferenceDose; + this->update(); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + setIsoDoseLevel(mitk::IsoDoseLevel* level) +{ + if (level != m_IsoDoseLevel) + { + if(!level) + { + mitkThrow() << "Error. Cannot set iso dose level for widget to NULL pointer."; + } + + this->m_IsoDoseLevel = level; + this->update(); + } +} + +void QmitkFreeIsoDoseLevelWidget:: + OnRelValueChanged(double newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/100.0); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnAbsValueChanged(double newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/this->m_ReferenceDose); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnSliderChanged(int newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/100.0); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnVisibleClicked(bool checked) +{ + this->m_IsoDoseLevel->SetVisibleIsoLine(checked); + emit VisualizationStyleChanged(this->m_IsoDoseLevel); +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnColorChanged(QColor color) +{ + mitk::IsoDoseLevel::ColorType doseColor; + doseColor.SetRed(color.redF()); + doseColor.SetGreen(color.greenF()); + doseColor.SetBlue(color.blueF()); + this->m_IsoDoseLevel->SetColor(doseColor); + emit ColorChanged(this->m_IsoDoseLevel); +}; + +void QmitkFreeIsoDoseLevelWidget:: + updateValue(mitk::DoseValueRel newDose) +{ + m_InternalUpdate = true; + + mitk::DoseValueRel oldValue = this->m_IsoDoseLevel->GetDoseValue(); + this->m_IsoDoseLevel->SetDoseValue(newDose); + this->sbAbsValue->setValue(newDose*this->m_ReferenceDose); + this->sbRelValue->setValue(newDose*100); + this->doseSlider->setValue(newDose*100); + + m_InternalUpdate = false; + + emit ValueChanged(this->m_IsoDoseLevel,oldValue); +}; + +void QmitkFreeIsoDoseLevelWidget:: + update() +{ + updateValue(this->m_IsoDoseLevel->GetDoseValue()); + + this->checkVisibleIso->setChecked(this->m_IsoDoseLevel->GetVisibleIsoLine()); + + QColor color; + color.setRgbF(this->m_IsoDoseLevel->GetColor().GetRed(),this->m_IsoDoseLevel->GetColor().GetGreen(),this->m_IsoDoseLevel->GetColor().GetBlue()); + this->colorBtn->setColor(color); +}; diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h new file mode 100644 index 0000000000..8973071578 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h @@ -0,0 +1,78 @@ +/*=================================================================== + +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 QMITK_FREE_ISO_DOSE_LEVEL_WIDGET_H +#define QMITK_FREE_ISO_DOSE_LEVEL_WIDGET_H + +#include "MitkRTUIExports.h" + +#include "ui_QmitkFreeIsoDoseLevelWidget.h" +#include + +#include "mitkIsoDoseLevel.h" + +/** +* \class QmitkFreeIsoDoseLevelWidget +* \brief Widget that allows to show and edit the content of an mitk::IsoDoseLevel instance. +*/ +class MitkRTUI_EXPORT QmitkFreeIsoDoseLevelWidget : public QWidget, private Ui::QmitkFreeIsoDoseLevelWidget +{ + Q_OBJECT + +public: + QmitkFreeIsoDoseLevelWidget(QWidget* parent=0); + + mitk::DoseValueAbs getReferenceDose() const; + mitk::IsoDoseLevel* getIsoDoseLevel() const; + +signals: + void ValueChanged(mitk::IsoDoseLevel*, mitk::DoseValueRel oldValue); + void ColorChanged(mitk::IsoDoseLevel*); + void VisualizationStyleChanged(mitk::IsoDoseLevel*); + + public Q_SLOTS: + /** + * \brief Slot that can be used to set the reference dose. + */ + void setReferenceDose(double newReferenceDose); + + /** + * \brief Slot that can be used to set the dose level instance that should be handled by the widget. + */ + void setIsoDoseLevel(mitk::IsoDoseLevel* level); + + void OnRelValueChanged(double newValue); + void OnAbsValueChanged(double newValue); + void OnSliderChanged(int newValue); + void OnVisibleClicked(bool checked); + void OnColorChanged(QColor color); + +protected: + + /** + * \brief Updates the widget according to its current settings. + */ + void update(); + void updateValue(mitk::DoseValueRel newDose); + + mitk::DoseValueAbs m_ReferenceDose; + mitk::IsoDoseLevel::Pointer m_IsoDoseLevel; + bool m_InternalUpdate; + +}; + +#endif // QmitkFreeIsoDoseLevelWidget_H diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui new file mode 100644 index 0000000000..1f168c8044 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui @@ -0,0 +1,201 @@ + + + QmitkFreeIsoDoseLevelWidget + + + + 0 + 0 + 395 + 32 + + + + Form + + + + 2 + + + + + + 0 + 0 + + + + + 40 + 16777215 + + + + Color of the iso dose level + + + + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + 150 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + 0 + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + % + + + 9999.000000000000000 + + + 0.500000000000000 + + + + + + + = + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Minimum dose value of this level. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Gy + + + 9999.000000000000000 + + + 0.500000000000000 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Show isoline for this dose level + + + Qt::LeftToRight + + + + + + + :/RTUI/eye_open.png + :/RTUI/eye_open.png + :/RTUI/eye_open.png:/RTUI/eye_open.png + + + + 24 + 16 + + + + false + + + + + + + + ctkColorPickerButton + QPushButton +
ctkColorPickerButton.h
+
+
+ + + + +
diff --git a/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp new file mode 100644 index 0000000000..18348d2073 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp @@ -0,0 +1,450 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "QmitkIsoDoseLevelSetModel.h" +#include "mitkRTUIConstants.h" + +QmitkIsoDoseLevelSetModel:: + QmitkIsoDoseLevelSetModel(QObject *parent) : +QAbstractTableModel(parent), m_referenceDose(mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE), m_showAbsoluteDose(false), m_visibilityEditOnly(false), m_modified(false) +{ + m_DoseSet = mitk::IsoDoseLevelSet::New(); +} + +void + QmitkIsoDoseLevelSetModel:: + setIsoDoseLevelSet(mitk::IsoDoseLevelSet *pSet) +{ + if (pSet) + { + emit beginResetModel(); + + m_DoseSet = pSet; + m_modified = false; + + emit endResetModel(); + } +}; + +int + QmitkIsoDoseLevelSetModel:: + rowCount(const QModelIndex &parent) const +{ + if(parent.isValid()) + { + return 0; + } + + return m_DoseSet->Size(); +} + +int + QmitkIsoDoseLevelSetModel:: + columnCount(const QModelIndex &parent) const +{ + if(parent.isValid()) + return 0; + + return 4; +} + +QVariant + QmitkIsoDoseLevelSetModel:: + data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + QVariant result; + + if(index.row()Size()) + { + const mitk::IsoDoseLevel& level = m_DoseSet->GetIsoDoseLevel(static_cast(index.row())); + + switch(index.column()) + { + case 0: + if(role == Qt::EditRole || role == Qt::DecorationRole) + { + QColor color; + color.setRgbF(level.GetColor().GetRed(),level.GetColor().GetGreen(),level.GetColor().GetBlue()); + result = QVariant(color); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Color of the iso dose level."); + } + break; + case 1: + if(role == Qt::DisplayRole) + { + if (this->m_showAbsoluteDose) + { + result = QVariant(QString::number(level.GetDoseValue()*this->m_referenceDose)+QString(" Gy")); + } + else + { + result = QVariant(QString::number(level.GetDoseValue()*100)+QString(" %")); + } + } + else if(role == Qt::EditRole) + { + if (this->m_showAbsoluteDose) + { + result = QVariant(level.GetDoseValue()*this->m_referenceDose); + } + else + { + result = QVariant(level.GetDoseValue()*100); + } + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Minimum dose value of this level / Value of the iso line."); + } + else if (role == Qt::UserRole+1) + { + result = QVariant(this->m_showAbsoluteDose); + } + break; + case 2: + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(level.GetVisibleIsoLine()); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Show isoline for this dose level."); + } + break; + case 3: + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(level.GetVisibleColorWash()); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Show colorwash for this dose level."); + } + break; + } + } + + return result; +} + +Qt::ItemFlags + QmitkIsoDoseLevelSetModel:: + flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + + if(index.row()Size()) + { + if (index.column() < 4) + { + if ((index.column() > 1) || (index.column() >= 0 && !this->m_visibilityEditOnly)) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + } + else if (index.column() >= 0 && this->m_visibilityEditOnly) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + + } + } + + return flags; +} + +QVariant + QmitkIsoDoseLevelSetModel:: + headerData(int section, Qt::Orientation orientation, int role) const +{ + if( (Qt::DisplayRole == role) && + (Qt::Horizontal == orientation)) + { + if (section==0) + { + return QVariant("Color"); + } + else if (section==1) + { + if (m_showAbsoluteDose) + { + return QVariant("Dose [Gy]"); + } + else + { + return QVariant("Dose [%]"); + } + } + else if (section==2) + { + return QVariant("IsoLines"); + } + else if (section==3) + { + return QVariant("ColorWash"); + } + } + return QVariant(); +} + +bool + QmitkIsoDoseLevelSetModel:: + setData(const QModelIndex &index, const QVariant &value, int role) +{ + if(!index.isValid() || (m_DoseSet->Size() <= index.row()) || (index.column()>3)) + { + return false; + } + + if(Qt::EditRole == role) + { + const mitk::IsoDoseLevel& level = m_DoseSet->GetIsoDoseLevel(static_cast(index.row())); + mitk::IsoDoseLevel::Pointer pNewLevel = level.Clone(); + switch(index.column()) + { + case 0: + { + QColor val = value.value(); + mitk::IsoDoseLevel::ColorType color; + color.SetRed(val.redF()); + color.SetGreen(val.greenF()); + color.SetBlue(val.blueF()); + pNewLevel->SetColor(color); + emit dataChanged(index,index); + break; + } + case 1: + if (this->m_showAbsoluteDose) + { + pNewLevel->SetDoseValue(value.toDouble()/this->m_referenceDose); + } + else + { + pNewLevel->SetDoseValue(value.toDouble()/100.0); + } + emit dataChanged(index,index); + break; + case 2: + pNewLevel->SetVisibleIsoLine(value.toBool()); + emit dataChanged(index,index); + break; + case 3: + pNewLevel->SetVisibleColorWash(value.toBool()); + emit dataChanged(index,index); + break; + } + + emit beginResetModel(); + + m_DoseSet->DeleteIsoDoseLevel(static_cast(index.row())); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + + m_modified = true; + + emit endResetModel(); + + return true; + } + + return false; +}; + +void QmitkIsoDoseLevelSetModel:: + setReferenceDose(double newReferenceDose) +{ + if (newReferenceDose<= 0) + { + mitkThrow() << "Error. Passed prescribed dose is negative or equals 0."; + } + + if (newReferenceDose != m_referenceDose) + { + this->m_referenceDose = newReferenceDose; + if(m_showAbsoluteDose) + { + emit beginResetModel(); + emit endResetModel(); + } + } +}; + +void QmitkIsoDoseLevelSetModel:: + setShowAbsoluteDose(bool showAbsoluteDose) + +{ + if (showAbsoluteDose != m_showAbsoluteDose) + { + emit beginResetModel(); + this->m_showAbsoluteDose = showAbsoluteDose; + emit endResetModel(); + } +}; + +void QmitkIsoDoseLevelSetModel::setVisibilityEditOnly(bool onlyVisibility) +{ + if (onlyVisibility != m_visibilityEditOnly) + { + emit beginResetModel(); + this->m_visibilityEditOnly = onlyVisibility; + emit endResetModel(); + } +}; + +bool + QmitkIsoDoseLevelSetModel:: + getShowAbsoluteDose() const +{ + return this->m_showAbsoluteDose; +}; + +mitk::DoseValueAbs + QmitkIsoDoseLevelSetModel:: + getReferenceDose() const +{ + return this->m_referenceDose; +}; + +bool + QmitkIsoDoseLevelSetModel:: + getVisibilityEditOnly() const +{ + return this->m_visibilityEditOnly; +}; + +void QmitkIsoDoseLevelSetModel::switchVisibilityIsoLines(bool activate) +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleIsoLine(activate); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::switchVisibilityColorWash(bool activate) +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleColorWash(activate); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::invertVisibilityIsoLines() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleIsoLine(!pNewLevel->GetVisibleIsoLine()); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::invertVisibilityColorWash() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleColorWash(!pNewLevel->GetVisibleColorWash()); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::swapVisibility() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + bool colorWash = pNewLevel->GetVisibleColorWash(); + pNewLevel->SetVisibleColorWash(pNewLevel->GetVisibleIsoLine()); + pNewLevel->SetVisibleIsoLine(colorWash); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::addLevel() +{ + mitk::IsoDoseLevel::DoseValueType doseVal = 0.01; + + if (m_DoseSet->Size()>0) + { + doseVal = m_DoseSet->GetIsoDoseLevel(m_DoseSet->Size()-1).GetDoseValue()+0.01; + } + + mitk::IsoDoseLevel::Pointer pNewLevel = mitk::IsoDoseLevel::New(doseVal, mitk::IsoDoseLevel::ColorType(), true, true); + + emit beginResetModel(); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + m_modified = true; + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::deleteLevel(const QModelIndex &index) +{ + if(!index.isValid() || (m_DoseSet->Size() <= index.row()) || (index.column()>3)) + { + return; + } + + emit beginResetModel(); + m_DoseSet->DeleteIsoDoseLevel(static_cast(index.row())); + m_modified = true; + emit endResetModel(); +} + +bool QmitkIsoDoseLevelSetModel::isModified() +{ + return m_modified; +} diff --git a/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h new file mode 100644 index 0000000000..0940072072 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h @@ -0,0 +1,98 @@ +/*=================================================================== + +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 QmitkIsoDoseLevelSetModel_h +#define QmitkIsoDoseLevelSetModel_h + +#include + +#include "mitkIsoDoseLevelCollections.h" + +#include "MitkRTUIExports.h" + + +/*! +\class QmitkIsoDoseLevelSetModel +Model that handles a iso dose level set and allows viewing and editing of its contents. +Please see special delegates (QmitkDoseColorDelegate, QmitkDoseValueDelegate, QmitkDoseVisualStyleDelegate) to +handle visualization and editing in views that work on this model. +\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. +*/ +class MitkRTUI_EXPORT QmitkIsoDoseLevelSetModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + QmitkIsoDoseLevelSetModel(QObject *parent = NULL); + virtual ~QmitkIsoDoseLevelSetModel() {}; + + /** Sets the data handled by the model and resets the modified flag*/ + void setIsoDoseLevelSet(mitk::IsoDoseLevelSet *pSet); + + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + bool getShowAbsoluteDose() const; + mitk::DoseValueAbs getReferenceDose() const; + + bool getVisibilityEditOnly() const; + + void switchVisibilityIsoLines(bool activate); + void switchVisibilityColorWash(bool activate); + void invertVisibilityIsoLines(); + void invertVisibilityColorWash(); + void swapVisibility(); + + void addLevel(); + void deleteLevel(const QModelIndex &index); + + /**Indicates if the content of the model was modified since the data was set via setIsoDoseLevelSet()*/ + bool isModified(); + + public Q_SLOTS: + /** + * \brief Slot that can be used to set the prescribed dose. + */ + void setReferenceDose(double newReferenceDose); + /** + * \brief Slot that can be used to adjust whether the dose should be displayed in absolute or relative units. + */ + void setShowAbsoluteDose(bool showAbsoluteDose); + + /** + * \brief Slat that can be used to adjust wether the model allows to edit only visibilities (no dose value or color) + */ + void setVisibilityEditOnly(bool onlyVisibility); + +private: + mitk::IsoDoseLevelSet::Pointer m_DoseSet; + + bool m_showAbsoluteDose; + bool m_visibilityEditOnly; + + mitk::DoseValueAbs m_referenceDose; + + /** Indicates if the data of the model was modified, since the model was set. */ + bool m_modified; + +}; + +#endif // QmitkIsoDoseLevelSetModel_h + diff --git a/Modules/RTUI/files.cmake b/Modules/RTUI/files.cmake new file mode 100644 index 0000000000..d49a968f4c --- /dev/null +++ b/Modules/RTUI/files.cmake @@ -0,0 +1,27 @@ +set(CPP_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.cpp + Qmitk/QmitkIsoDoseLevelSetModel.cpp + Qmitk/QmitkDoseColorDelegate.cpp + Qmitk/QmitkDoseValueDelegate.cpp + Qmitk/QmitkDoseVisualStyleDelegate.cpp + Helper/mitkRTUIConstants.cpp + Helper/mitkIsoLevelsGenerator.cpp +) + +set(UI_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.ui +) + +set(MOC_H_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.h + Qmitk/QmitkIsoDoseLevelSetModel.h + Qmitk/QmitkDoseColorDelegate.h + Qmitk/QmitkDoseValueDelegate.h + Qmitk/QmitkDoseVisualStyleDelegate.h +) + +set(QRC_FILES + resources/RTUI.qrc +) + + diff --git a/Modules/RTUI/resources/RTUI.qrc b/Modules/RTUI/resources/RTUI.qrc new file mode 100644 index 0000000000..174c9563ea --- /dev/null +++ b/Modules/RTUI/resources/RTUI.qrc @@ -0,0 +1,8 @@ + + + powerGreen.png + eye_close.png + eye_open.png + powerRed.png + + diff --git a/Modules/RTUI/resources/eye_close.png b/Modules/RTUI/resources/eye_close.png new file mode 100644 index 0000000000..9b82203c2a Binary files /dev/null and b/Modules/RTUI/resources/eye_close.png differ diff --git a/Modules/RTUI/resources/eye_open.png b/Modules/RTUI/resources/eye_open.png new file mode 100644 index 0000000000..a1c2bb9f35 Binary files /dev/null and b/Modules/RTUI/resources/eye_open.png differ diff --git a/Modules/RTUI/resources/powerGreen.png b/Modules/RTUI/resources/powerGreen.png new file mode 100644 index 0000000000..9e8e0903d9 Binary files /dev/null and b/Modules/RTUI/resources/powerGreen.png differ diff --git a/Modules/RTUI/resources/powerRed.png b/Modules/RTUI/resources/powerRed.png new file mode 100644 index 0000000000..bb3f33bef5 Binary files /dev/null and b/Modules/RTUI/resources/powerRed.png differ diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 8483a5f304..f8bfa9d856 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,53 +1,54 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF + org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.igtlplugin:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF ) diff --git a/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt b/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt index 69b3cb5d2c..a2881c78d5 100644 --- a/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt @@ -1,26 +1,26 @@ project(org_mitk_gui_qt_dicom) find_program(DCMTK_STORESCP NAMES storescp storescp${DCMTK_CMAKE_DEBUG_POSTFIX} storescp${CMAKE_DEBUG_POSTFIX} PATHS "${DCMTK_DIR}/bin" PATH_SUFFIXES Release Debug DOC "Dcmtk storage provider which is used to store dicom files which are transfered over network." NO_DEFAULT_PATH ) mark_as_advanced(DCMTK_STORESCP) if(NOT EXISTS ${DCMTK_STORESCP}) message(WARNING "Couldn't find program storescp without the program query retrieve of the dicom plugin won't work!") else(NOT EXISTS ${DCMTK_STORESCP}) configure_file( org_mitk_gui_qt_dicom_config.h.in org_mitk_gui_qt_dicom_config.h @ONLY) MITK_INSTALL_HELPER_APP(${DCMTK_STORESCP}) MACRO_CREATE_MITK_CTK_PLUGIN( EXPORT_DIRECTIVE DICOM_EXPORT EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkQtWidgetsExt MitkDicomUI + MODULE_DEPENDS MitkQtWidgetsExt MitkDicomUI MitkDicomRT MitkRTUI ) endif() diff --git a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp index 57ec40acb6..00a850f2d1 100644 --- a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp +++ b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp @@ -1,98 +1,277 @@ /*=================================================================== 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 "mitkPluginActivator.h" #include "DicomEventHandler.h" #include #include #include #include #include #include #include #include #include #include #include "mitkImage.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include DicomEventHandler::DicomEventHandler() { } DicomEventHandler::~DicomEventHandler() { } void DicomEventHandler::OnSignalAddSeriesToDataManager(const ctkEvent& ctkEvent) { - QStringList listOfFilesForSeries; - mitk::DicomSeriesReader::StringContainer seriesToLoad; + QStringList listOfFilesForSeries; + mitk::DicomSeriesReader::StringContainer seriesToLoad; + + listOfFilesForSeries = ctkEvent.getProperty("FilesForSeries").toStringList(); + + if (!listOfFilesForSeries.isEmpty()){ - listOfFilesForSeries = ctkEvent.getProperty("FilesForSeries").toStringList(); + //for rt data, if the modality tag isnt defined or is "CT" the image is handled like before + if(ctkEvent.containsProperty("Modality") && + (ctkEvent.getProperty("Modality").toString().compare("RTDOSE",Qt::CaseInsensitive) == 0 || + ctkEvent.getProperty("Modality").toString().compare("RTSTRUCT",Qt::CaseInsensitive) == 0)) + { + QString modality = ctkEvent.getProperty("Modality").toString(); - if (!listOfFilesForSeries.isEmpty()){ + if(modality.compare("RTDOSE",Qt::CaseInsensitive) == 0) + { + mitk::RTDoseReader::Pointer doseReader = mitk::RTDoseReader::New(); - QStringListIterator it(listOfFilesForSeries); + mitk::DataNode::Pointer doseImageNode = mitk::DataNode::New(); + mitk::DataNode::Pointer doseOutlineNode = mitk::DataNode::New(); - while (it.hasNext()) + doseImageNode = doseReader->LoadRTDose(listOfFilesForSeries.at(0).toStdString().c_str()); + doseOutlineNode->SetData(doseImageNode->GetData()); + if(doseImageNode.IsNotNull() && doseOutlineNode->GetData() != NULL) { - seriesToLoad.push_back(it.next().toStdString()); - } + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + typedef std::vector NamesType; + NamesType names = prefNode->ChildrenNames(); + + std::map presetMap; + + for (NamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + berry::IPreferences::Pointer aPresetNode = prefNode->Node(*pos); + + if (aPresetNode.IsNull()) + { + mitkThrow()<< "Error in preference interface. Cannot find preset node under given name. Name: "<<*pos; + } + + mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); + + NamesType levelNames = aPresetNode->ChildrenNames(); + for (NamesType::const_iterator levelName = levelNames.begin(); levelName != levelNames.end(); ++levelName) + { + berry::IPreferences::Pointer levelNode = aPresetNode->Node(*levelName); + if (aPresetNode.IsNull()) + { + mitkThrow()<< "Error in preference interface. Cannot find level node under given preset name. Name: "<<*pos<<"; Level id: "<<*levelName; + } + + mitk::IsoDoseLevel::Pointer isoLevel = mitk::IsoDoseLevel::New(); + + isoLevel->SetDoseValue(levelNode->GetDouble(mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID,0.0)); + mitk::IsoDoseLevel::ColorType color; + color.SetRed(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID,1.0)); + color.SetGreen(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID,1.0)); + color.SetBlue(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID,1.0)); + isoLevel->SetColor(color); + isoLevel->SetVisibleIsoLine(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID,true)); + isoLevel->SetVisibleColorWash(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID,true)); + + levelSet->SetIsoDoseLevel(isoLevel); + } + + presetMap.insert(std::make_pair(*pos,levelSet)); + } + + if (presetMap.size() == 0) + { + presetMap.insert(std::make_pair(std::string("Virtuos"), mitk::GeneratIsoLevels_Virtuos())); + } + + double referenceDose = 40.0; + //set some specific colorwash and isoline properties + doseImageNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), true); + doseOutlineNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), true); + //Set reference dose property + doseImageNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); + doseOutlineNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); + + berry::IPreferences::Pointer nameNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + std::string presetName = nameNode->Get(mitk::RTUIConstants::SELECTED_ISO_PRESET_ID,""); + mitk::IsoDoseLevelSet::Pointer isoDoseLevelPreset = presetMap[presetName]; + mitk::IsoDoseLevelSetProperty::Pointer levelSetProp = mitk::IsoDoseLevelSetProperty::New(isoDoseLevelPreset); - mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(seriesToLoad); - if (node.IsNull()) + doseImageNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),levelSetProp); + doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),levelSetProp); + + mitk::IsoDoseLevelVector::Pointer levelVector = mitk::IsoDoseLevelVector::New(); + mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(levelVector); + doseImageNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),levelVecProp); + doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),levelVecProp); + + //Generating the Colorwash + vtkSmartPointer transferFunction = vtkSmartPointer::New(); + + for(mitk::IsoDoseLevelSet::ConstIterator itIsoDoseLevel = isoDoseLevelPreset->Begin(); itIsoDoseLevel != isoDoseLevelPreset->End(); ++itIsoDoseLevel) + { + float *hsv = new float[3]; + //used for transfer rgb to hsv + vtkSmartPointer cCalc = vtkSmartPointer::New(); + if(itIsoDoseLevel->GetVisibleColorWash()){ + cCalc->RGBToHSV(itIsoDoseLevel->GetColor()[0],itIsoDoseLevel->GetColor()[1],itIsoDoseLevel->GetColor()[2],&hsv[0],&hsv[1],&hsv[2]); + transferFunction->AddHSVPoint(itIsoDoseLevel->GetDoseValue()*referenceDose,hsv[0],hsv[1],hsv[2],1.0,1.0); + } + } + + mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); + mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); + mitkTransFunc->SetColorTransferFunction(transferFunction); + mitkTransFuncProp->SetValue(mitkTransFunc); + + mitk::RenderingModeProperty::Pointer renderingModeProp = mitk::RenderingModeProperty::New(); + renderingModeProp->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); + + doseImageNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); + doseImageNode->SetProperty("Image Rendering.Mode", renderingModeProp); + doseImageNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); + + //set the outline properties + doseOutlineNode->SetBoolProperty("outline binary", true); + doseOutlineNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); + doseOutlineNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false) ); + + ctkServiceReference serviceReference =mitk::PluginActivator::getContext()->getServiceReference(); + mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); + mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); + + dataStorage->Add(doseImageNode); + dataStorage->Add(doseOutlineNode, doseImageNode); + + //set the dose mapper for outline drawing; the colorwash is realized by the imagevtkmapper2D + mitk::DoseImageVtkMapper2D::Pointer contourMapper = mitk::DoseImageVtkMapper2D::New(); + doseOutlineNode->SetMapper(1,contourMapper); + + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); + }//END DOSE + } + else if(modality.compare("RTSTRUCT",Qt::CaseInsensitive) == 0) + { + mitk::RTStructureSetReader::Pointer structreader = mitk::RTStructureSetReader::New(); + std::deque modelVector = structreader->ReadStructureSet(listOfFilesForSeries.at(0).toStdString().c_str()); + + if(modelVector.empty()) { - MITK_ERROR << "Error loading series: " << ctkEvent.getProperty("SeriesName").toString().toStdString() - << " id: " <getServiceReference(); - mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); - mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); - - dataStorage->Add(node); + ctkServiceReference serviceReference =mitk::PluginActivator::getContext()->getServiceReference(); + mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); + mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); - // Initialize the RenderWindow - mitk::TimeGeometry::Pointer geometry = dataStorage->ComputeBoundingGeometry3D(dataStorage->GetAll()); - mitk::RenderingManager::GetInstance()->InitializeViews(geometry); + for(int i=0; iAdd(modelVector.at(i)); + } + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); } + } } else { - MITK_INFO << "There are no files for the current series"; + + QStringListIterator it(listOfFilesForSeries); + + while (it.hasNext()) + { + seriesToLoad.push_back(it.next().toStdString()); + } + + + mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(seriesToLoad); + if (node.IsNull()) + { + MITK_ERROR << "Error loading series: " << ctkEvent.getProperty("SeriesName").toString().toStdString() + << " id: " <getServiceReference(); + mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); + mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); + + dataStorage->Add(node); + } } + } + else + { + MITK_INFO << "There are no files for the current series"; + } } void DicomEventHandler::OnSignalRemoveSeriesFromStorage(const ctkEvent& ctkEvent) { } void DicomEventHandler::SubscribeSlots() { - ctkServiceReference ref = mitk::PluginActivator::getContext()->getServiceReference(); - if (ref) - { - ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService(ref); - ctkDictionary properties; - properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/ADD"; - eventAdmin->subscribeSlot(this, SLOT(OnSignalAddSeriesToDataManager(ctkEvent)), properties); - properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/DELETED"; - eventAdmin->subscribeSlot(this, SLOT(OnSignalRemoveSeriesFromStorage(ctkEvent)), properties); - } + ctkServiceReference ref = mitk::PluginActivator::getContext()->getServiceReference(); + if (ref) + { + ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService(ref); + ctkDictionary properties; + properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/ADD"; + eventAdmin->subscribeSlot(this, SLOT(OnSignalAddSeriesToDataManager(ctkEvent)), properties); + properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/DELETED"; + eventAdmin->subscribeSlot(this, SLOT(OnSignalRemoveSeriesFromStorage(ctkEvent)), properties); + } } diff --git a/Plugins/org.mitk.gui.qt.dicom/src/internal/QmitkDicomBrowser.cpp b/Plugins/org.mitk.gui.qt.dicom/src/internal/QmitkDicomBrowser.cpp index fbfa7ccff2..6322595332 100644 --- a/Plugins/org.mitk.gui.qt.dicom/src/internal/QmitkDicomBrowser.cpp +++ b/Plugins/org.mitk.gui.qt.dicom/src/internal/QmitkDicomBrowser.cpp @@ -1,202 +1,206 @@ /*=================================================================== 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. ===================================================================*/ // Qmitk #include "QmitkDicomBrowser.h" #include "mitkPluginActivator.h" #include "berryIQtPreferencePage.h" #include #include #include #include const std::string QmitkDicomBrowser::EDITOR_ID = "org.mitk.editors.dicombrowser"; const QString QmitkDicomBrowser::TEMP_DICOM_FOLDER_SUFFIX="TmpDicomFolder"; QmitkDicomBrowser::QmitkDicomBrowser() : m_Thread(new QThread()) , m_DicomDirectoryListener(new QmitkDicomDirectoryListener()) , m_StoreSCPLauncher(new QmitkStoreSCPLauncher(&m_Builder)) , m_Publisher(new QmitkDicomDataEventPublisher()) { } QmitkDicomBrowser::~QmitkDicomBrowser() { m_Thread.quit(); m_Thread.wait(1000); delete m_DicomDirectoryListener; delete m_StoreSCPLauncher; delete m_Handler; delete m_Publisher; } void QmitkDicomBrowser::CreateQtPartControl(QWidget *parent ) { m_Controls.setupUi( parent ); m_Controls.StoreSCPStatusLabel->setTextFormat(Qt::RichText); m_Controls.StoreSCPStatusLabel->setText(""); TestHandler(); OnPreferencesChanged(0); CreateTemporaryDirectory(); StartDicomDirectoryListener(); m_Controls.m_ctkDICOMQueryRetrieveWidget->useProgressDialog(false); connect(m_Controls.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int))); connect(m_Controls.externalDataWidget,SIGNAL(SignalStartDicomImport(const QStringList&)), m_Controls.internalDataWidget,SLOT(OnStartDicomImport(const QStringList&))); connect(m_Controls.externalDataWidget,SIGNAL(SignalDicomToDataManager(const QHash&)), this,SLOT(OnViewButtonAddToDataManager(const QHash&))); connect(m_Controls.internalDataWidget,SIGNAL(SignalFinishedImport()),this, SLOT(OnDicomImportFinished())); connect(m_Controls.internalDataWidget,SIGNAL(SignalDicomToDataManager(const QHash&)), this,SLOT(OnViewButtonAddToDataManager(const QHash&))); } void QmitkDicomBrowser::Init(berry::IEditorSite::Pointer site, berry::IEditorInput::Pointer input) { this->SetSite(site); this->SetInput(input); } void QmitkDicomBrowser::SetFocus() { } berry::IPartListener::Events::Types QmitkDicomBrowser::GetPartEventTypes() const { return Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void QmitkDicomBrowser::OnTabChanged(int page) { if (page == 2)//Query/Retrieve is selected { QString storagePort = m_Controls.m_ctkDICOMQueryRetrieveWidget->getServerParameters()["StoragePort"].toString(); QString storageAET = m_Controls.m_ctkDICOMQueryRetrieveWidget->getServerParameters()["StorageAETitle"].toString(); if(!((m_Builder.GetAETitle()->compare(storageAET,Qt::CaseSensitive)==0)&& (m_Builder.GetPort()->compare(storagePort,Qt::CaseSensitive)==0))) { StopStoreSCP(); StartStoreSCP(); } } } void QmitkDicomBrowser::OnDicomImportFinished() { m_Controls.tabWidget->setCurrentIndex(0); } void QmitkDicomBrowser::StartDicomDirectoryListener() { if(!m_Thread.isRunning()) { m_DicomDirectoryListener->SetDicomListenerDirectory(m_TempDirectory); m_DicomDirectoryListener->SetDicomFolderSuffix(TEMP_DICOM_FOLDER_SUFFIX); connect(m_DicomDirectoryListener,SIGNAL(SignalStartDicomImport(const QStringList&)),m_Controls.internalDataWidget,SLOT(OnStartDicomImport(const QStringList&)),Qt::DirectConnection); //connect(m_Controls.internalDataWidget,SIGNAL(SignalFinishedImport()),m_DicomDirectoryListener,SLOT(OnImportFinished()),Qt::DirectConnection); m_DicomDirectoryListener->moveToThread(&m_Thread); m_Thread.start(); } } void QmitkDicomBrowser::TestHandler() { m_Handler = new DicomEventHandler(); m_Handler->SubscribeSlots(); } void QmitkDicomBrowser::OnViewButtonAddToDataManager(QHash eventProperties) { ctkDictionary properties; // properties["PatientName"] = eventProperties["PatientName"]; // properties["StudyUID"] = eventProperties["StudyUID"]; // properties["StudyName"] = eventProperties["StudyName"]; // properties["SeriesUID"] = eventProperties["SeriesUID"]; // properties["SeriesName"] = eventProperties["SeriesName"]; properties["FilesForSeries"] = eventProperties["FilesForSeries"]; + if(eventProperties.contains("Modality")) + { + properties["Modality"] = eventProperties["Modality"]; + } m_Publisher->PublishSignals(mitk::PluginActivator::getContext()); m_Publisher->AddSeriesToDataManagerEvent(properties); } void QmitkDicomBrowser::StartStoreSCP() { QString storagePort = m_Controls.m_ctkDICOMQueryRetrieveWidget->getServerParameters()["StoragePort"].toString(); QString storageAET = m_Controls.m_ctkDICOMQueryRetrieveWidget->getServerParameters()["StorageAETitle"].toString(); m_Builder.AddPort(storagePort)->AddAETitle(storageAET)->AddTransferSyntax()->AddOtherNetworkOptions()->AddMode()->AddOutputDirectory(m_TempDirectory); m_StoreSCPLauncher = new QmitkStoreSCPLauncher(&m_Builder); connect(m_StoreSCPLauncher, SIGNAL(SignalStatusOfStoreSCP(const QString&)), this, SLOT(OnStoreSCPStatusChanged(const QString&))); connect(m_StoreSCPLauncher ,SIGNAL(SignalStartImport(const QStringList&)),m_Controls.internalDataWidget,SLOT(OnStartDicomImport(const QStringList&))); connect(m_StoreSCPLauncher ,SIGNAL(SignalStoreSCPError(const QString&)),m_DicomDirectoryListener,SLOT(OnDicomNetworkError(const QString&)),Qt::DirectConnection); connect(m_StoreSCPLauncher ,SIGNAL(SignalStoreSCPError(const QString&)),this,SLOT(OnDicomNetworkError(const QString&)),Qt::DirectConnection); m_StoreSCPLauncher->StartStoreSCP(); } void QmitkDicomBrowser::OnStoreSCPStatusChanged(const QString& status) { m_Controls.StoreSCPStatusLabel->setText(" "+status); } void QmitkDicomBrowser::OnDicomNetworkError(const QString& status) { m_Controls.StoreSCPStatusLabel->setText(" "+status); } void QmitkDicomBrowser::StopStoreSCP() { delete m_StoreSCPLauncher; } void QmitkDicomBrowser::SetPluginDirectory() { m_PluginDirectory = mitk::PluginActivator::getContext()->getDataFile("").absolutePath(); m_PluginDirectory.append("/database"); } void QmitkDicomBrowser::CreateTemporaryDirectory() { QDir tmp; QString tmpPath = QDir::tempPath(); m_TempDirectory.clear(); m_TempDirectory.append(tmpPath); m_TempDirectory.append(QString("/")); m_TempDirectory.append(TEMP_DICOM_FOLDER_SUFFIX); m_TempDirectory.append(QString(".")); m_TempDirectory.append(QTime::currentTime().toString("hhmmsszzz")); m_TempDirectory.append(QString::number(QCoreApplication::applicationPid())); tmp.mkdir(QDir::toNativeSeparators( m_TempDirectory )); } void QmitkDicomBrowser::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { SetPluginDirectory(); berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); m_DatabaseDirectory = prefService->GetSystemPreferences()->Node("/org.mitk.views.dicomreader")->Get("default dicom path", m_PluginDirectory); m_Controls.internalDataWidget->SetDatabaseDirectory(m_DatabaseDirectory); } diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/CMakeLists.txt b/Plugins/org.mitk.gui.qt.dosevisualization/CMakeLists.txt new file mode 100644 index 0000000000..e4b727388d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_dosevisualization) + +MACRO_CREATE_MITK_CTK_PLUGIN( + EXPORT_DIRECTIVE RTDOSEVISUALIZATION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkDicomRT MitkRTUI +) diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/files.cmake b/Plugins/org.mitk.gui.qt.dosevisualization/files.cmake new file mode 100644 index 0000000000..e726795cdc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/files.cmake @@ -0,0 +1,52 @@ +set(SRC_CPP_FILES +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_dosevisualization_Activator.cpp + RTDoseVisualizer.cpp + RTUIPreferencePage.cpp + DoseVisualizationPreferencePage.cpp + mitkDoseVisPreferenceHelper.cpp +) + +set(UI_FILES + src/internal/RTDoseVisualizerControls.ui + src/internal/DoseVisualizationPreferencePageControls.ui + src/internal/RTUIPreferencePageControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_dosevisualization_Activator.h + src/internal/RTDoseVisualizer.h + src/internal/RTUIPreferencePage.h + src/internal/DoseVisualizationPreferencePage.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/iso.png + resources/iso2.png + resources/icon4.png + resources/icon5.png + resources/icon7.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.dosevisualization/manifest_headers.cmake new file mode 100644 index 0000000000..9492c2783b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "RTDoseVisualization") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ, Software development for Integrated Diagnostic and Therapy") +set(Plugin-ContactAddress "sbr@dkfz-heidelber.de") +set(Require-Plugin org.mitk.gui.qt.common org.commontk.eventadmin) diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/plugin.xml b/Plugins/org.mitk.gui.qt.dosevisualization/plugin.xml new file mode 100644 index 0000000000..26cc3804f3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/plugin.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon4.png b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon4.png new file mode 100644 index 0000000000..07e3d5d412 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon4.png differ diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon5.png b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon5.png new file mode 100644 index 0000000000..a3338ef126 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon5.png differ diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon7.png b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon7.png new file mode 100644 index 0000000000..55f6b4cbf3 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.dosevisualization/resources/icon7.png differ diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso.png b/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso.png new file mode 100644 index 0000000000..7edf418042 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso.png differ diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso2.png b/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso2.png new file mode 100644 index 0000000000..2a73d321db Binary files /dev/null and b/Plugins/org.mitk.gui.qt.dosevisualization/resources/iso2.png differ diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp new file mode 100644 index 0000000000..5b3ff7b048 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp @@ -0,0 +1,377 @@ +/*=================================================================== + +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 "DoseVisualizationPreferencePage.h" +#include "mitkRTUIConstants.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "mitkIsoLevelsGenerator.h" + +#include "org_mitk_gui_qt_dosevisualization_Activator.h" + +DoseVisualizationPreferencePage::DoseVisualizationPreferencePage() + : m_MainControl(0), m_Controls(0), m_referenceDoseChanged(false), m_presetMapChanged(false) +{ + +} + +DoseVisualizationPreferencePage::~DoseVisualizationPreferencePage() +{ + delete m_LevelSetModel; + delete m_DoseColorDelegate; + delete m_DoseValueDelegate; + delete m_DoseVisualDelegate; + delete m_Controls; +} + +void DoseVisualizationPreferencePage::Init(berry::IWorkbench::Pointer ) +{ + +} + +void DoseVisualizationPreferencePage::CreateQtControl(QWidget* parent) +{ + berry::IPreferencesService::Pointer prefService + = berry::Platform::GetServiceRegistry() + .GetServiceById(berry::IPreferencesService::ID); + + m_DoseVisNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + m_MainControl = new QWidget(parent); + m_Controls = new Ui::DoseVisualizationPreferencePageControls; + m_Controls->setupUi( m_MainControl ); + + m_LevelSetModel = new QmitkIsoDoseLevelSetModel(this); + m_DoseColorDelegate = new QmitkDoseColorDelegate(this); + m_DoseValueDelegate = new QmitkDoseValueDelegate(this); + m_DoseVisualDelegate = new QmitkDoseVisualStyleDelegate(this); + + this->m_Controls->isoLevelSetView->setModel(m_LevelSetModel); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(0,m_DoseColorDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(1,m_DoseValueDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(2,m_DoseVisualDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(3,m_DoseVisualDelegate); + this->m_Controls->isoLevelSetView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(m_Controls->spinReferenceDose, SIGNAL(valueChanged(double)), m_LevelSetModel, SLOT(setReferenceDose(double))); + connect(m_Controls->spinReferenceDose, SIGNAL(valueChanged(double)), this, SLOT(OnReferenceDoseChanged(double))); + connect(m_Controls->checkGlobalSync, SIGNAL(toggled(bool)), m_Controls->spinReferenceDose, SLOT(setEnabled(bool))); + connect(m_Controls->radioAbsDose, SIGNAL(toggled(bool)), m_LevelSetModel, SLOT(setShowAbsoluteDose(bool))); + connect(m_Controls->isoLevelSetView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnShowContextMenuIsoSet(const QPoint&))); + connect(m_Controls->listPresets, SIGNAL(currentItemChanged ( QListWidgetItem *, QListWidgetItem *)), this, SLOT(OnCurrentItemChanged ( QListWidgetItem *, QListWidgetItem *))); + connect(m_Controls->btnAddPreset, SIGNAL(clicked(bool)), this, SLOT(OnAddPresetClicked(bool))); + connect(m_Controls->btnDelPreset, SIGNAL(clicked(bool)), this, SLOT(OnDelPresetClicked(bool))); + connect(m_Controls->btnResetPreset, SIGNAL(clicked(bool)), this, SLOT(OnResetPresetClicked(bool))); + connect(m_Controls->btnDelLevel, SIGNAL(clicked(bool)), this, SLOT(OnDelLevelClicked(bool))); + connect(m_Controls->btnAddLevel, SIGNAL(clicked(bool)), this, SLOT(OnAddLevelClicked(bool))); + + this->Update(); +} + +QWidget* DoseVisualizationPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +bool DoseVisualizationPreferencePage::PerformOk() +{ + m_DoseVisNode->PutBool(mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID,m_Controls->radioAbsDose->isChecked()); + m_DoseVisNode->PutBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID,m_Controls->checkGlobalVisColorWash->isChecked()); + m_DoseVisNode->PutBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_ISOLINES_ID,m_Controls->checkGlobalVisIsoLine->isChecked()); + m_DoseVisNode->PutDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID,m_Controls->spinReferenceDose->value()); + m_DoseVisNode->PutBool(mitk::RTUIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, m_Controls->checkGlobalSync->isChecked()); + + mitk::StorePresetsMap(this->m_Presets); + + if (this->m_Presets.find(this->m_selectedPresetName)==this->m_Presets.end()) + { //the preset currently selected in the application is not available any more. Change it to a valid one. + mitk::SetSelectedPresetName(this->m_Presets.begin()->first); + } + + if (this->m_LevelSetModel->isModified()) + { + this->m_presetMapChanged = true; + } + + if (m_referenceDoseChanged) + { + mitk::SignalReferenceDoseChange(m_Controls->checkGlobalSync->isChecked(), m_Controls->spinReferenceDose->value(), mitk::org_mitk_gui_qt_dosevisualization_Activator::GetContext()); + } + + if (m_presetMapChanged) + { + mitk::SignalPresetMapChange(mitk::org_mitk_gui_qt_dosevisualization_Activator::GetContext()); + } + + return true; +} + +void DoseVisualizationPreferencePage::PerformCancel() +{ +} + +void DoseVisualizationPreferencePage::Update() +{ + m_Controls->checkGlobalVisColorWash->setChecked(m_DoseVisNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID, true)); + m_Controls->checkGlobalVisIsoLine->setChecked(m_DoseVisNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_ISOLINES_ID, true)); + m_Controls->radioAbsDose->setChecked(m_DoseVisNode->GetBool(mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID, true)); + m_Controls->radioRelDose->setChecked(!(m_DoseVisNode->GetBool(mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID, false))); + m_Controls->spinReferenceDose->setValue(m_DoseVisNode->GetDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID, mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE)); + m_Controls->checkGlobalSync->setChecked(m_DoseVisNode->GetBool(mitk::RTUIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, true)); + + m_referenceDoseChanged = false; + m_presetMapChanged = false; + + + berry::IPreferences::Pointer presetsNode = m_DoseVisNode->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + this->m_Presets = mitk::LoadPresetsMap(); + this->m_selectedPresetName = mitk::GetSelectedPresetName(); + UpdatePresetsWidgets(); +} + + +mitk::IsoDoseLevelSet* DoseVisualizationPreferencePage::GetSelectedIsoLevelSet() +{ + QListWidgetItem* selectedItem = m_Controls->listPresets->currentItem(); + + mitk::IsoDoseLevelSet::Pointer result; + + if (selectedItem) + { + result = m_Presets[selectedItem->text().toStdString()]; + } + + return result; +} + +void DoseVisualizationPreferencePage::UpdateLevelSetWidgets() +{ + this->m_Controls->btnAddLevel->setEnabled(this->GetSelectedIsoLevelSet()!=NULL); + + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + this->m_Controls->btnDelLevel->setEnabled(this->GetSelectedIsoLevelSet()!=NULL && selectedIndex.isValid()); +} + +void DoseVisualizationPreferencePage::UpdatePresetsWidgets() +{ + m_Controls->listPresets->clear(); + + QListWidgetItem* selectedItem = NULL; + for (PresetMapType::iterator pos = m_Presets.begin(); pos != m_Presets.end(); ++pos) + { + QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(pos->first)); + if (!selectedItem) + { + selectedItem = item; + } + + m_Controls->listPresets->addItem(item); + } + + if (selectedItem) + { + m_Controls->listPresets->setCurrentItem(selectedItem); + } + + if (this->m_LevelSetModel->isModified()) + { + this->m_presetMapChanged = true; + } + + this->m_LevelSetModel->setIsoDoseLevelSet(this->GetSelectedIsoLevelSet()); + + m_Controls->btnDelPreset->setEnabled((m_Controls->listPresets->currentItem() != NULL) && (m_Controls->listPresets->count()>1)); +} + +void DoseVisualizationPreferencePage::OnCurrentItemChanged ( QListWidgetItem * currentItem, QListWidgetItem * previousItem) +{ + this->m_LevelSetModel->setIsoDoseLevelSet(this->GetSelectedIsoLevelSet()); +} + +void DoseVisualizationPreferencePage::OnShowContextMenuIsoSet(const QPoint& pos) +{ + QPoint globalPos = m_Controls->isoLevelSetView->viewport()->mapToGlobal(pos); + + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + + QMenu viewMenu; + QAction* addLevelAct = viewMenu.addAction("Add new level"); + QAction* delLevelAct = viewMenu.addAction("Delete selected level"); + delLevelAct->setEnabled(selectedIndex.isValid()); + viewMenu.addSeparator(); + QAction* invertIsoLineAct = viewMenu.addAction("Invert iso line visibility"); + QAction* activateIsoLineAct = viewMenu.addAction("Activate all iso lines"); + QAction* deactivateIsoLineAct = viewMenu.addAction("Deactivate all iso lines"); + viewMenu.addSeparator(); + QAction* invertColorWashAct = viewMenu.addAction("Invert color wash visibility"); + QAction* activateColorWashAct = viewMenu.addAction("Activate all color wash levels"); + QAction* deactivateColorWashAct = viewMenu.addAction("Deactivate all color wash levels"); + viewMenu.addSeparator(); + QAction* swapAct = viewMenu.addAction("Swap iso line/color wash visibility"); + + QAction* selectedItem = viewMenu.exec(globalPos); + if (selectedItem == invertIsoLineAct) + { + this->m_LevelSetModel->invertVisibilityIsoLines(); + } + else if (selectedItem == activateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(true); + } + else if (selectedItem == deactivateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(false); + } + else if (selectedItem == invertColorWashAct) + { + this->m_LevelSetModel->invertVisibilityColorWash(); + } + else if (selectedItem == activateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(true); + } + else if (selectedItem == deactivateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(false); + } + else if (selectedItem == swapAct) + { + this->m_LevelSetModel->swapVisibility(); + } + else if (selectedItem == addLevelAct) + { + this->m_LevelSetModel->addLevel(); + } + else if (selectedItem == delLevelAct) + { + this->m_LevelSetModel->deleteLevel(selectedIndex); + } +} + +void DoseVisualizationPreferencePage::OnAddPresetClicked(bool checked) +{ + bool done = false; + QString name = tr("new_preset"); + while (!done) + { + bool ok; + name = QInputDialog::getText(m_MainControl, tr("Define name of new preset."), tr("Preset name:"), QLineEdit::Normal, name, &ok); + + if (!ok) + { + return; //cancled by user; + } + + bool uniqueName = m_Presets.find(name.toStdString()) == m_Presets.end(); + if (!uniqueName) + { + QMessageBox box; + box.setText(tr("New preset name is not unique. Please, choose another one.")); + box.exec(); + } + + bool validName = name.indexOf(tr("/")) ==-1; + if (!validName) + { + QMessageBox box; + box.setText(tr("New preset name is not valid. Please don't use \"/\".")); + box.exec(); + } + + done = uniqueName && validName; + } + + mitk::IsoDoseLevelSet::Pointer newSet = mitk::GeneratIsoLevels_Virtuos(); + m_Presets.insert(std::make_pair(name.toStdString(),newSet)); + + m_presetMapChanged = true; + + UpdatePresetsWidgets(); +} + +void DoseVisualizationPreferencePage::OnDelPresetClicked(bool checked) +{ + QListWidgetItem* selectedItem = m_Controls->listPresets->currentItem(); + + if (selectedItem) + { + if (m_Controls->listPresets->count() > 1) + { + m_Presets.erase(selectedItem->text().toStdString()); + + m_presetMapChanged = true; + this->UpdatePresetsWidgets(); + } + } +} + + +void DoseVisualizationPreferencePage::OnResetPresetClicked(bool checked) +{ + QMessageBox box; + box.setText("Do you want to reset the presets?"); + box.setInformativeText("If you reset the presets. All user defined presets will be removed and the default presets will be loaded."); + box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + box.setDefaultButton(QMessageBox::No); + int ret = box.exec(); + + if (ret == QMessageBox::Yes) + { + mitk::IsoDoseLevelSet::Pointer newSet = mitk::GeneratIsoLevels_Virtuos(); + m_Presets.clear(); + m_Presets.insert(std::make_pair("Virtuos",newSet)); + + m_presetMapChanged = true; + + UpdatePresetsWidgets(); + } +} + + +void DoseVisualizationPreferencePage::OnAddLevelClicked(bool checked) +{ + this->m_LevelSetModel->addLevel(); +} + +void DoseVisualizationPreferencePage::OnDelLevelClicked(bool checked) +{ + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + + if (!selectedIndex.isValid()) + { + selectedIndex = m_Controls->isoLevelSetView->indexAt(QPoint(1,1)); + } + + this->m_LevelSetModel->deleteLevel(selectedIndex); +} + +void DoseVisualizationPreferencePage::OnReferenceDoseChanged(double dose) +{ + this->m_referenceDoseChanged = true; +}; diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h new file mode 100644 index 0000000000..e2835ecc14 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h @@ -0,0 +1,123 @@ +/*=================================================================== + +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 __DOSE_VISUALIZATION_PREFERENCE_PAGE_H +#define __DOSE_VISUALIZATION_PREFERENCE_PAGE_H + +#include "berryIQtPreferencePage.h" +#include "berryIPreferences.h" + +#include "ui_DoseVisualizationPreferencePageControls.h" + +#include +#include "mitkDoseVisPreferenceHelper.h" + +/*forward declarations*/ +class QmitkIsoDoseLevelSetModel; +class QmitkDoseColorDelegate; +class QmitkDoseValueDelegate; +class QmitkDoseVisualStyleDelegate; + +class QWidget; + +/** +* \class DoseVisualizationPreferencePage +* \brief Preference page for RT Dose visualization +*/ +class DoseVisualizationPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + DoseVisualizationPreferencePage(); + ~DoseVisualizationPreferencePage(); + + /** + * \brief Called by framework to initialize this preference page, but currently does nothing. + * \param workbench The workbench. + */ + void Init(berry::IWorkbench::Pointer workbench); + + /** + * \brief Called by framework to create the GUI, and connect signals and slots. + * \param widget The Qt widget that acts as parent to all GUI components, as this class itself is not derived from QWidget. + */ + void CreateQtControl(QWidget* widget); + + /** + * \brief Required by framework to get hold of the GUI. + * \return QWidget* the top most QWidget for the GUI. + */ + QWidget* GetQtControl() const; + + /** + * \see IPreferencePage::PerformOk + */ + virtual bool PerformOk(); + + /** + * \see IPreferencePage::PerformCancel + */ + virtual void PerformCancel(); + + /** + * \see IPreferencePage::Update + */ + virtual void Update(); + + public slots: + + void OnCurrentItemChanged ( QListWidgetItem * currentItem, QListWidgetItem * previousItem); + void OnShowContextMenuIsoSet(const QPoint& pos); + void OnAddPresetClicked(bool checked); + void OnDelPresetClicked(bool checked); + void OnResetPresetClicked(bool checked); + void OnAddLevelClicked(bool checked); + void OnDelLevelClicked(bool checked); + void OnReferenceDoseChanged(double dose); + +protected: + + /** Method updates the presets widgets according to the internal members*/ + void UpdatePresetsWidgets(); + /** Method actualizes the level set model and edit buttons according to the currently selected item in the presets list view*/ + void UpdateLevelSetWidgets(); + + /** Method returns the iso dose level set selected in the preset lists. May return NULL if no preset is selected.*/ + mitk::IsoDoseLevelSet* GetSelectedIsoLevelSet(); + + QWidget *m_MainControl; + Ui::DoseVisualizationPreferencePageControls* m_Controls; + + berry::IPreferences::Pointer m_DoseVisNode; + + typedef mitk::PresetMapType PresetMapType; + PresetMapType m_Presets; + std::string m_selectedPresetName; + + bool m_referenceDoseChanged; + bool m_presetMapChanged; + + QmitkIsoDoseLevelSetModel* m_LevelSetModel; + QmitkDoseColorDelegate* m_DoseColorDelegate; + QmitkDoseValueDelegate* m_DoseValueDelegate; + QmitkDoseVisualStyleDelegate* m_DoseVisualDelegate; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui new file mode 100644 index 0000000000..ffbdbcad21 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui @@ -0,0 +1,307 @@ + + + DoseVisualizationPreferencePageControls + + + + 0 + 0 + 714 + 651 + + + + + 0 + 0 + + + + QmitkTemplate + + + + 5 + + + 5 + + + + + Global viszualization settings: + + + + + + + 0 + 0 + + + + + 105 + 0 + + + + Qt::NoFocus + + + Reference dose [Gy]: + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Dose display: + + + + + + + + + relative [%] + + + true + + + + + + + absolute [Gy] + + + + + + + + + Global visibility: + + + + + + + + + Isolines + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + Colorwash + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + + + + + + + + + + + 1 + + + 0.100000000000000 + + + 9999.000000000000000 + + + + + + + global sync + + + + + + + + + + + + Iso dose level presets: + + + + 5 + + + 5 + + + + + + 16777215 + 100 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Remove + + + + + + + Reset + + + + + + + + + Preset editor: + + + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 30 + 20 + + + + 75 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add level + + + + + + + Remove level + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.cpp b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.cpp new file mode 100644 index 0000000000..7442bf652c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.cpp @@ -0,0 +1,636 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// Qt +#include +#include + +// Blueberry +#include +#include + +// MITK +#include + +#include +#include + +// Qmitk +#include "RTDoseVisualizer.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "org_mitk_gui_qt_dosevisualization_Activator.h" + +#include +#include +#include + +#include "QmitkRenderWindow.h" + +#include "vtkDecimatePro.h" + +const std::string RTDoseVisualizer::VIEW_ID = "org.mitk.views.rt.dosevisualization"; + +RTDoseVisualizer::RTDoseVisualizer() +{ + m_selectedNode = NULL; + m_selectedPresetName = ""; + m_internalUpdate = false; + m_PrescribedDose_Data = 0.0; + m_freeIsoValuesCount = 0; +} + +RTDoseVisualizer::~RTDoseVisualizer() +{ + delete m_LevelSetModel; + delete m_DoseColorDelegate; + delete m_DoseValueDelegate; + delete m_DoseVisualDelegate; +} + +void RTDoseVisualizer::SetFocus(){} + +void RTDoseVisualizer::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + + m_LevelSetModel = new QmitkIsoDoseLevelSetModel(this); + m_LevelSetModel->setVisibilityEditOnly(true); + m_DoseColorDelegate = new QmitkDoseColorDelegate(this); + m_DoseValueDelegate = new QmitkDoseValueDelegate(this); + m_DoseVisualDelegate = new QmitkDoseVisualStyleDelegate(this); + + this->UpdateByPreferences(); + this->ActualizeIsoLevelsForAllDoseDataNodes(); + this->ActualizeReferenceDoseForAllDoseDataNodes(); + this->ActualizeDisplayStyleForAllDoseDataNodes(); + + this->m_Controls.isoLevelSetView->setModel(m_LevelSetModel); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(0,m_DoseColorDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(1,m_DoseValueDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(2,m_DoseVisualDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(3,m_DoseVisualDelegate); + this->m_Controls.isoLevelSetView->setContextMenuPolicy(Qt::CustomContextMenu); + + this->m_Controls.btnRemoveFreeValue->setDisabled(true); + + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), this, SLOT(OnReferenceDoseChanged(double))); + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), m_LevelSetModel, SLOT(setReferenceDose(double))); + connect(m_Controls.radioAbsDose, SIGNAL(toggled(bool)), m_LevelSetModel, SLOT(setShowAbsoluteDose(bool))); + connect(m_Controls.radioAbsDose, SIGNAL(toggled(bool)), this, SLOT(OnAbsDoseToggled(bool))); + connect(m_Controls.btnAddFreeValue, SIGNAL(clicked()), this, SLOT(OnAddFreeValueClicked())); + connect(m_Controls.btnRemoveFreeValue, SIGNAL(clicked()), this, SLOT(OnRemoveFreeValueClicked())); + connect(m_Controls.checkGlobalVisColorWash, SIGNAL(toggled(bool)), this, SLOT(OnGlobalVisColorWashToggled(bool))); + connect(m_Controls.checkGlobalVisIsoLine, SIGNAL(toggled(bool)), this, SLOT(OnGlobalVisIsoLineToggled(bool))); + connect(m_Controls.isoLevelSetView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnShowContextMenuIsoSet(const QPoint&))); + connect(m_Controls.comboPresets, SIGNAL(currentIndexChanged ( const QString&)), this, SLOT(OnCurrentPresetChanged(const QString&))); + connect(m_Controls.btnUsePrescribedDose, SIGNAL(clicked()), this, SLOT(OnUsePrescribedDoseClicked())); + connect(m_Controls.isoLevelSetView->model(), SIGNAL( modelReset()), this, SLOT(OnDataChangedInIsoLevelSetView())); + + ctkServiceReference ref = mitk::org_mitk_gui_qt_dosevisualization_Activator::GetContext()->getServiceReference(); + + ctkDictionary propsForSlot; + if (ref) + { + ctkEventAdmin* eventAdmin = mitk::org_mitk_gui_qt_dosevisualization_Activator::GetContext()->getService(ref); + + propsForSlot[ctkEventConstants::EVENT_TOPIC] = mitk::RTCTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED.c_str(); + eventAdmin->subscribeSlot(this, SLOT(OnHandleCTKEventPresetsChanged(ctkEvent)), propsForSlot); + + propsForSlot[ctkEventConstants::EVENT_TOPIC] = mitk::RTCTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED.c_str(); + eventAdmin->subscribeSlot(this, SLOT(OnHandleCTKEventReferenceDoseChanged(ctkEvent)), propsForSlot); + } + + this->UpdateBySelectedNode(); +} + +void RTDoseVisualizer::OnReferenceDoseChanged(double value) +{ + if (! m_internalUpdate) + { + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::GetReferenceDoseValue(referenceDose); + + if (globalSync) + { + mitk::SetReferenceDoseValue(globalSync, value); + this->ActualizeReferenceDoseForAllDoseDataNodes(); + } + else + { + if (this->m_selectedNode.IsNotNull()) + { + this->m_selectedNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + isoDoseNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + } + } + if (this->m_selectedNode.IsNotNull()) + { + this->UpdateColorWashTransferFunction(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + } +} + +void RTDoseVisualizer::OnAddFreeValueClicked() +{ + QColor newColor; + //Use HSV schema of QColor to calculate a different color depending on the + //number of already existing free iso lines. + newColor.setHsv((m_freeIsoValuesCount*85)%360,255,255); + mitk::IsoDoseLevel::ColorType mColor; + mColor[0]=newColor.redF(); + mColor[1]=newColor.greenF(); + mColor[2]=newColor.blueF(); + + mitk::IsoDoseLevelVector::Pointer freeIsoDoseVector; + mitk::IsoDoseLevelVectorProperty::Pointer propIsoVector; + + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + propIsoVector = dynamic_cast(isoDoseNode->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + + freeIsoDoseVector = propIsoVector->GetValue(); + if (freeIsoDoseVector.IsNull()) + mitk::IsoDoseLevelVector::Pointer freeIsoDoseVector = mitk::IsoDoseLevelVector::New(); + + mitk::IsoDoseLevel::Pointer newLevel = mitk::IsoDoseLevel::New(0.5,mColor,true,false); + freeIsoDoseVector->InsertElement(m_freeIsoValuesCount,newLevel); + propIsoVector = mitk::IsoDoseLevelVectorProperty::New(freeIsoDoseVector); + + isoDoseNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),propIsoVector); + + m_freeIsoValuesCount++; + this->m_Controls.btnRemoveFreeValue->setEnabled(true); + //Update Widget + this->UpdateFreeIsoValues(); + //Update Rendering + this->ActualizeFreeIsoLine(); +} + +void RTDoseVisualizer::OnRemoveFreeValueClicked() +{ + int index = this->m_Controls.listFreeValues->currentRow(); + if (index > m_freeIsoValuesCount || index < 0) + return; + + mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec; + + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + propfreeIsoVec = dynamic_cast(isoDoseNode->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + + mitk::IsoDoseLevelVector::Pointer freeIsoDoseLevelVec = propfreeIsoVec->GetValue(); + if(freeIsoDoseLevelVec->IndexExists(index)) + { + //freeIsoDoseLevelVec->DeleteIndex(index); + freeIsoDoseLevelVec->erase(freeIsoDoseLevelVec->begin()+index); + --m_freeIsoValuesCount; + if(m_freeIsoValuesCount == 0) + this->m_Controls.btnRemoveFreeValue->setEnabled(true); + this->UpdateFreeIsoValues(); + this->ActualizeFreeIsoLine(); + } + +} + +void RTDoseVisualizer::OnUsePrescribedDoseClicked() +{ + m_Controls.spinReferenceDose->setValue(this->m_PrescribedDose_Data); +} + +void RTDoseVisualizer::OnDataChangedInIsoLevelSetView() +{ + //colorwash visibility changed, update the colorwash + this->UpdateColorWashTransferFunction(); + + //Hack: This is a dirty hack to reinit the isodose contour node. Only if the node (or property) has changed the rendering process register the RequestUpdateAll + //Only way to render the isoline by changes without a global reinit + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + isoDoseNode->Modified(); + + // Reinit if visibility of colorwash or isodoselevel changed + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void RTDoseVisualizer::OnShowContextMenuIsoSet(const QPoint& pos) +{ + QPoint globalPos = m_Controls.isoLevelSetView->viewport()->mapToGlobal(pos); + + QMenu viewMenu; + QAction* invertIsoLineAct = viewMenu.addAction("Invert iso line visibility"); + QAction* activateIsoLineAct = viewMenu.addAction("Activate all iso lines"); + QAction* deactivateIsoLineAct = viewMenu.addAction("Deactivate all iso lines"); + viewMenu.addSeparator(); + QAction* invertColorWashAct = viewMenu.addAction("Invert color wash visibility"); + QAction* activateColorWashAct = viewMenu.addAction("Activate all color wash levels"); + QAction* deactivateColorWashAct = viewMenu.addAction("Deactivate all color wash levels"); + viewMenu.addSeparator(); + QAction* swapAct = viewMenu.addAction("Swap iso line/color wash visibility"); + // ... + + QAction* selectedItem = viewMenu.exec(globalPos); + if (selectedItem == invertIsoLineAct) + { + this->m_LevelSetModel->invertVisibilityIsoLines(); + } + else if (selectedItem == activateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(true); + } + else if (selectedItem == deactivateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(false); + } + else if (selectedItem == invertColorWashAct) + { + this->m_LevelSetModel->invertVisibilityColorWash(); + } + else if (selectedItem == activateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(true); + } + else if (selectedItem == deactivateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(false); + } + else if (selectedItem == swapAct) + { + this->m_LevelSetModel->swapVisibility(); + } +} + +void RTDoseVisualizer::UpdateFreeIsoValues() +{ + this->m_Controls.listFreeValues->clear(); + + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec; + + propfreeIsoVec = dynamic_cast(isoDoseNode->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + + + mitk::IsoDoseLevelVector::Pointer freeIsoDoseLevelVec = propfreeIsoVec->GetValue(); + + for (mitk::IsoDoseLevelVector::Iterator pos = freeIsoDoseLevelVec->Begin(); pos != freeIsoDoseLevelVec->End(); ++pos) + { + QListWidgetItem* item = new QListWidgetItem; + item->setSizeHint(QSize(0,25)); + QmitkFreeIsoDoseLevelWidget* widget = new QmitkFreeIsoDoseLevelWidget; + + float pref; + m_selectedNode->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + + widget->setIsoDoseLevel(pos.Value()); + widget->setReferenceDose(pref); + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), widget, SLOT(setReferenceDose(double))); + connect(widget,SIGNAL(ColorChanged(mitk::IsoDoseLevel*)), this, SLOT(ActualizeFreeIsoLine())); + connect(widget,SIGNAL(ValueChanged(mitk::IsoDoseLevel*,mitk::DoseValueRel)), this, SLOT(ActualizeFreeIsoLine())); + connect(widget,SIGNAL(VisualizationStyleChanged(mitk::IsoDoseLevel*)), this, SLOT(ActualizeFreeIsoLine())); + + this->m_Controls.listFreeValues->addItem(item); + this->m_Controls.listFreeValues->setItemWidget(item,widget); + } +} + +void RTDoseVisualizer::ActualizeFreeIsoLine() +{ + //Hack: This is a dirty hack to reinit the isodose contour node. Only if the node (or property) has changed the rendering process register the RequestUpdateAll + //Only way to render the isoline by changes without a global reinit + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + isoDoseNode->Modified(); + + // Reinit if visibility of colorwash or isodoselevel changed + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} +void RTDoseVisualizer::OnAbsDoseToggled(bool showAbs) +{ + if (! m_internalUpdate) + { + mitk::SetDoseDisplayAbsolute(showAbs); + this->ActualizeDisplayStyleForAllDoseDataNodes(); + } +} + +void RTDoseVisualizer::OnGlobalVisColorWashToggled(bool showColorWash) +{ + if (m_selectedNode.IsNotNull()) + { + m_selectedNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), showColorWash); + //The rendering mode could be set in the dose mapper: Refactoring! + mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); + if(showColorWash) + renderingMode->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); + else + renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); + m_selectedNode->SetProperty("Image Rendering.Mode", renderingMode); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void RTDoseVisualizer::OnGlobalVisIsoLineToggled(bool showIsoLines) +{ + if (m_selectedNode.IsNotNull()) + { + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + isoDoseNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), showIsoLines); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void RTDoseVisualizer::UpdateColorWashTransferFunction() +{ + //Generating the Colorwash + vtkSmartPointer transferFunction = vtkSmartPointer::New(); + + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast(m_selectedNode->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = propIsoSet->GetValue(); + + float referenceDose; + m_selectedNode->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),referenceDose); + mitk::TransferFunction::ControlPoints scalarOpacityPoints; + scalarOpacityPoints.push_back( std::make_pair(0, 1 ) ); + //Backgroud + transferFunction->AddHSVPoint(((isoDoseLevelSet->Begin())->GetDoseValue()*referenceDose)-0.001,0,0,0,1.0,1.0); + + for(mitk::IsoDoseLevelSet::ConstIterator itIsoDoseLevel = isoDoseLevelSet->Begin(); itIsoDoseLevel != isoDoseLevelSet->End(); ++itIsoDoseLevel) + { + float *hsv = new float[3]; + //used for transfer rgb to hsv + vtkSmartPointer cCalc = vtkSmartPointer::New(); + + if(itIsoDoseLevel->GetVisibleColorWash()) + { + cCalc->RGBToHSV(itIsoDoseLevel->GetColor()[0],itIsoDoseLevel->GetColor()[1],itIsoDoseLevel->GetColor()[2],&hsv[0],&hsv[1],&hsv[2]); + transferFunction->AddHSVPoint(itIsoDoseLevel->GetDoseValue()*referenceDose,hsv[0],hsv[1],hsv[2],1.0,1.0); + } + else + { + scalarOpacityPoints.push_back( std::make_pair(itIsoDoseLevel->GetDoseValue()*referenceDose, 1 ) ); + } + } + + mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); + mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); + mitkTransFunc->SetColorTransferFunction(transferFunction); + mitkTransFunc->SetScalarOpacityPoints(scalarOpacityPoints); + mitkTransFuncProp->SetValue(mitkTransFunc); + m_selectedNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); +} + +void RTDoseVisualizer::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes ) +{ + QList dataNodes = this->GetDataManagerSelection(); + + mitk::DataNode* selectedNode = NULL; + + if (!dataNodes.empty()) + { + bool isDoseNode = false; + dataNodes[0]->GetBoolProperty(mitk::RTConstants::DOSE_PROPERTY_NAME.c_str(),isDoseNode); + + if (isDoseNode) + { + selectedNode = dataNodes[0]; + } + } + + if (selectedNode != m_selectedNode.GetPointer()) + { + m_selectedNode = selectedNode; + } + + UpdateBySelectedNode(); +} + +void RTDoseVisualizer::UpdateBySelectedNode() +{ + m_Controls.groupNodeSpecific->setEnabled(m_selectedNode.IsNotNull()); + m_Controls.groupFreeValues->setEnabled(m_selectedNode.IsNotNull()); + m_Controls.checkGlobalVisColorWash->setEnabled(m_selectedNode.IsNotNull()); + m_Controls.checkGlobalVisIsoLine->setEnabled(m_selectedNode.IsNotNull()); + m_Controls.isoLevelSetView->setEnabled(m_selectedNode.IsNotNull()); + + + if(m_selectedNode.IsNull()) + { + m_Controls.NrOfFractions->setText(QString("N/A. No dose selected")); + m_Controls.prescribedDoseSpecific->setText(QString("N/A. No dose selected")); + } + else + { + //dose specific information + int fracCount = 1; + m_selectedNode->GetIntProperty(mitk::RTConstants::DOSE_FRACTION_COUNT_PROPERTY_NAME.c_str(),fracCount); + m_Controls.NrOfFractions->setText(QString::number(fracCount)); + + m_PrescribedDose_Data = 0.0; + + float tmp; + m_selectedNode->GetFloatProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),tmp); + m_PrescribedDose_Data = (double)tmp; + + m_Controls.prescribedDoseSpecific->setText(QString::number(m_PrescribedDose_Data)); + + //free iso lines + mitk::DataNode::Pointer isoDoseNode = this->GetIsoDoseNode(m_selectedNode); + mitk::IsoDoseLevelVectorProperty::Pointer propIsoVector; + + propIsoVector = dynamic_cast(isoDoseNode->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + + if (propIsoVector.IsNull()) + { + mitk::IsoDoseLevelVector::Pointer freeIsoValues = mitk::IsoDoseLevelVector::New(); + propIsoVector = mitk::IsoDoseLevelVectorProperty::New(freeIsoValues); + isoDoseNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),propIsoVector); + } + + UpdateFreeIsoValues(); + + //global dose issues + //ATM the IsoDoseContours have an own (helper) node which is a child of dose node; Will be fixed with the doseMapper refactoring + bool showIsoLine = false; + + isoDoseNode->GetBoolProperty(mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(),showIsoLine); + + m_Controls.checkGlobalVisIsoLine->setChecked(showIsoLine); + + bool showColorWash = false; + m_selectedNode->GetBoolProperty(mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(),showColorWash); + m_Controls.checkGlobalVisColorWash->setChecked(showColorWash); + + float referenceDose = 0.0; + m_selectedNode->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),referenceDose); + m_Controls.spinReferenceDose->setValue(referenceDose); + + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = + dynamic_cast(m_selectedNode->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + + if (propIsoSet) + { + this->m_LevelSetModel->setIsoDoseLevelSet(propIsoSet->GetValue()); + } + } +} + +void RTDoseVisualizer::UpdateByPreferences() +{ + m_Presets = mitk::LoadPresetsMap(); + m_internalUpdate = true; + m_Controls.comboPresets->clear(); + this->m_selectedPresetName = mitk::GetSelectedPresetName(); + + int index = 0; + int selectedIndex = -1; + for (mitk::PresetMapType::const_iterator pos = m_Presets.begin(); pos != m_Presets.end(); ++pos, ++index) + { + m_Controls.comboPresets->addItem(QString(pos->first.c_str())); + if (this->m_selectedPresetName == pos->first) + { + selectedIndex = index; + } + } + + if (selectedIndex == -1) + { + selectedIndex = 0; + MITK_WARN << "Error. Cannot iso dose level preset specified in preferences does not exist. Preset name: "<m_selectedPresetName; + this->m_selectedPresetName = m_Presets.begin()->first; + mitk::SetSelectedPresetName(this->m_selectedPresetName); + MITK_INFO << "Changed selected iso dose level preset to first existing preset. New preset name: "<m_selectedPresetName; + } + + m_Controls.comboPresets->setCurrentIndex(selectedIndex); + + this->m_LevelSetModel->setIsoDoseLevelSet(this->m_Presets[this->m_selectedPresetName]); + + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::GetReferenceDoseValue(referenceDose); + if (globalSync || this->m_selectedNode.IsNull()) + { + m_Controls.spinReferenceDose->setValue(referenceDose); + } + + bool displayAbsoluteDose = mitk::GetDoseDisplayAbsolute(); + m_Controls.radioAbsDose->setChecked(displayAbsoluteDose); + m_Controls.radioRelDose->setChecked(!displayAbsoluteDose); + this->m_LevelSetModel->setShowAbsoluteDose(displayAbsoluteDose); + m_internalUpdate = false; +} + +void RTDoseVisualizer::OnCurrentPresetChanged(const QString& presetName) +{ + if (! m_internalUpdate) + { + mitk::SetSelectedPresetName(presetName.toStdString()); + this->UpdateByPreferences(); + this->ActualizeIsoLevelsForAllDoseDataNodes(); + this->UpdateBySelectedNode(); + } +} + +void RTDoseVisualizer::ActualizeIsoLevelsForAllDoseDataNodes() +{ + std::string presetName = mitk::GetSelectedPresetName(); + + mitk::PresetMapType presetMap = mitk::LoadPresetsMap(); + + mitk::NodePredicateProperty::Pointer isDoseNode = mitk::NodePredicateProperty::New(mitk::RTConstants::DOSE_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + + mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetSubset(isDoseNode); + + mitk::IsoDoseLevelSet* selectedPreset = presetMap[presetName]; + + if (!selectedPreset) + { + mitkThrow() << "Error. Cannot actualize iso dose level preset. Selected preset idoes not exist. Preset name: "<begin(); pos != nodes->end(); ++pos) + { + mitk::IsoDoseLevelSet::Pointer clonedPreset = selectedPreset->Clone(); + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = mitk::IsoDoseLevelSetProperty::New(clonedPreset); + (*pos)->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),propIsoSet); + } +} + +void RTDoseVisualizer::ActualizeReferenceDoseForAllDoseDataNodes() +{ + /** @TODO Klären ob diese präsentations info genauso wie*/ + mitk::DoseValueAbs value = 0; + bool sync = mitk::GetReferenceDoseValue(value); + + if (sync) + { + mitk::NodePredicateProperty::Pointer isDoseNode = mitk::NodePredicateProperty::New(mitk::RTConstants::DOSE_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + + mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetSubset(isDoseNode); + + for(mitk::DataStorage::SetOfObjects::const_iterator pos = nodes->begin(); pos != nodes->end(); ++pos) + { + (*pos)->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + //ATM the IsoDoseContours have an own (helper) node which is a child of dose node; Will be fixed with the doseMapper refactoring + mitk::DataStorage::SetOfObjects::ConstPointer childNodes = this->GetDataStorage()->GetDerivations(*pos); + mitk::DataStorage::SetOfObjects::const_iterator iterChildNodes = childNodes->begin(); + + while (iterChildNodes != childNodes->end()) + { + (*iterChildNodes)->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + ++iterChildNodes; + } + } + } +} + +void RTDoseVisualizer::ActualizeDisplayStyleForAllDoseDataNodes() +{ + /** @TODO Klären ob diese präsentations info global oder auch per node gespeichert wird*/ +} + +void RTDoseVisualizer::OnHandleCTKEventReferenceDoseChanged(const ctkEvent& event) +{ + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::GetReferenceDoseValue(referenceDose); + + this->m_Controls.spinReferenceDose->setValue(referenceDose); +} + +void RTDoseVisualizer::OnHandleCTKEventPresetsChanged(const ctkEvent& event) +{ + std::string currentPresetName = mitk::GetSelectedPresetName(); + + this->OnCurrentPresetChanged(QString::fromStdString(currentPresetName)); +} + +//ATM the IsoDoseContours have an own (helper) node which is a child of dose node; Will be fixed with the doseMapper refactoring +mitk::DataNode::Pointer RTDoseVisualizer::GetIsoDoseNode(mitk::DataNode::Pointer doseNode) +{ + mitk::DataStorage::SetOfObjects::ConstPointer childNodes = this->GetDataStorage()->GetDerivations(doseNode); + return doseNode = (*childNodes->begin()); +} diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h new file mode 100644 index 0000000000..c39e6d90e4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h @@ -0,0 +1,162 @@ +/*=================================================================== + +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 RTDoseVisualizer_h +#define RTDoseVisualizer_h + +#include + +#include +#include + +#include "ui_RTDoseVisualizerControls.h" + +#include + +#include + +#include "mitkDoseVisPreferenceHelper.h" + +// Shader +#include +#include +#include + +#include +#include + +#include + +#include +#include + +/*forward declarations*/ +class QmitkIsoDoseLevelSetModel; +class QmitkDoseColorDelegate; +class QmitkDoseValueDelegate; +class QmitkDoseVisualStyleDelegate; +class ctkEvent; + +/** +\brief RTDoseVisualizer + +\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + +\sa QmitkAbstractView +\ingroup ${plugin_target}_internal +*/ +class RTDoseVisualizer : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + + RTDoseVisualizer(); + virtual ~RTDoseVisualizer(); + static const std::string VIEW_ID; + + void OnSliceChanged(itk::Object *sender, const itk::EventObject &e); + + protected slots: + + void OnAddFreeValueClicked(); + + void OnRemoveFreeValueClicked(); + + void OnUsePrescribedDoseClicked(); + + void OnDataChangedInIsoLevelSetView(); + + void OnAbsDoseToggled(bool); + + void OnGlobalVisColorWashToggled(bool); + + void OnGlobalVisIsoLineToggled(bool); + + void OnShowContextMenuIsoSet(const QPoint&); + + void OnCurrentPresetChanged(const QString&); + + void OnReferenceDoseChanged(double); + + void OnHandleCTKEventReferenceDoseChanged(const ctkEvent& event); + + void OnHandleCTKEventPresetsChanged(const ctkEvent& event); + + void ActualizeFreeIsoLine(); + +protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes ); + + /** Update the transfer funtion property for the color wash*/ + void UpdateColorWashTransferFunction(); + + /** Method updates the list widget according to the current free iso values.*/ + void UpdateFreeIsoValues(); + + /** Update the members according to the currently selected node */ + void UpdateBySelectedNode(); + + /** Update the member widgets according to the information stored in the application preferences*/ + void UpdateByPreferences(); + + /**helper function that iterates throug all data nodes and sets there iso level set property + according to the selected preset. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeIsoLevelsForAllDoseDataNodes(); + + /**helper function that iterates throug all data nodes and sets there reference dose value + according to the preference. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeReferenceDoseForAllDoseDataNodes(); + + /**helper function that iterates through all data nodes and sets there dose display style (relative/absolute) + according to the preference. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeDisplayStyleForAllDoseDataNodes(); + + Ui::RTDoseVisualizerControls m_Controls; + mitk::DataNode::Pointer m_selectedNode; + unsigned int m_freeIsoValuesCount; + + mitk::PresetMapType m_Presets; + std::string m_selectedPresetName; + + /** Prescribed Dose of the selected data.*/ + mitk::DoseValueAbs m_PrescribedDose_Data; + + QmitkIsoDoseLevelSetModel* m_LevelSetModel; + QmitkDoseColorDelegate* m_DoseColorDelegate; + QmitkDoseValueDelegate* m_DoseValueDelegate; + QmitkDoseVisualStyleDelegate* m_DoseVisualDelegate; + + bool m_internalUpdate; + +private: + mitk::DataNode::Pointer GetIsoDoseNode(mitk::DataNode::Pointer doseNode); +}; + +#endif // RTDoseVisualizer_h diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizerControls.ui b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizerControls.ui new file mode 100644 index 0000000000..c783cb8fb3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizerControls.ui @@ -0,0 +1,410 @@ + + + RTDoseVisualizerControls + + + + 0 + 0 + 421 + 651 + + + + + 0 + 0 + + + + QmitkTemplate + + + + 5 + + + 5 + + + + + Dose specific information: + + + + 5 + + + 5 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + 30 Gy + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + + Number of fractions: + + + + + + + Prescribed dose [Gy]: + + + + + + + Use as reference dose + + + + + + + true + + + + + + + + + + + + + 0 + 0 + + + + Free iso lines: + + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 110 + + + + + 0 + 25 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Remove + + + + + + + + + + + + Global iso dose visualization: + + + + 5 + + + 5 + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Dose display: + + + + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Preset style: + + + + + + + + 0 + 0 + + + + + 105 + 0 + + + + Qt::NoFocus + + + Reference dose [Gy]: + + + + + + + + + + 1 + + + 0.100000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + relative [%] + + + true + + + + + + + absolute [Gy] + + + + + + + + + + + false + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 30 + 20 + + + + 80 + + + + + + + + + Global visibility: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + Isolines + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + false + + + + + + + true + + + Colorwash + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.cpp b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.cpp new file mode 100644 index 0000000000..ed76d5f965 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.cpp @@ -0,0 +1,117 @@ +/*=================================================================== + +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 "RTUIPreferencePage.h" + +#include "mitkRTUIConstants.h" + +#include +#include + +//----------------------------------------------------------------------------- +RTUIPreferencePage::RTUIPreferencePage() + : m_MainControl(0), m_Controls(0) +{ + +} + + +//----------------------------------------------------------------------------- +RTUIPreferencePage::~RTUIPreferencePage() +{ + delete m_Controls; +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::Init(berry::IWorkbench::Pointer ) +{ + +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::CreateQtControl(QWidget* parent) +{ + berry::IPreferencesService::Pointer prefService + = berry::Platform::GetServiceRegistry() + .GetServiceById(berry::IPreferencesService::ID); + + m_PreferencesNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_PREFERENCE_NODE_ID); + + m_MainControl = new QWidget(parent); + m_Controls = new Ui::RTUIPreferencePageControls; + m_Controls->setupUi( m_MainControl ); + + connect(m_Controls->radioDefault, SIGNAL(toggled(bool)), m_Controls->spinDefault, SLOT(setEnabled(bool))); + connect(m_Controls->radioRelativeToMax, SIGNAL(toggled(bool)), m_Controls->spinRelativeToMax, SLOT(setEnabled(bool))); + + this->Update(); +} + + +//----------------------------------------------------------------------------- +QWidget* RTUIPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +//----------------------------------------------------------------------------- +bool RTUIPreferencePage::PerformOk() +{ + bool useAsDefaultValue = m_Controls->radioDefault->isChecked(); + m_PreferencesNode->PutBool(mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID,useAsDefaultValue); + + if (useAsDefaultValue) + { + m_PreferencesNode->PutDouble(mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, m_Controls->spinDefault->value()); + } + else + { + m_PreferencesNode->PutDouble(mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, m_Controls->spinRelativeToMax->value()/100.0); + } + + return true; +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::PerformCancel() +{ +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::Update() +{ + bool useAsDefaultValue = m_PreferencesNode->GetBool(mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID, true); + double doseValue = m_PreferencesNode->GetDouble(mitk::RTUIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, 50.0); + + m_Controls->radioDefault->setChecked(useAsDefaultValue); + m_Controls->radioRelativeToMax->setChecked(!useAsDefaultValue); + m_Controls->spinDefault->setEnabled(useAsDefaultValue); + m_Controls->spinRelativeToMax->setEnabled(!useAsDefaultValue); + + if (useAsDefaultValue) + { + m_Controls->spinDefault->setValue(doseValue); + } + else + { + m_Controls->spinRelativeToMax->setValue(doseValue*100.0); + } +} diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.h new file mode 100644 index 0000000000..208a41773f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePage.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 __RT_UI_PREFERENCE_PAGE_H +#define __RT_UI_PREFERENCE_PAGE_H + +#include "berryIQtPreferencePage.h" +#include "berryIPreferences.h" + +#include "ui_RTUIPreferencePageControls.h" + +class QWidget; + +/** +* \class RTUIPreferencePage +* \brief Preference page for general RT visualization settings. +*/ +class RTUIPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + RTUIPreferencePage(); + ~RTUIPreferencePage(); + + /** + * \brief Called by framework to initialize this preference page, but currently does nothing. + * \param workbench The workbench. + */ + void Init(berry::IWorkbench::Pointer workbench); + + /** + * \brief Called by framework to create the GUI, and connect signals and slots. + * \param widget The Qt widget that acts as parent to all GUI components, as this class itself is not derived from QWidget. + */ + void CreateQtControl(QWidget* widget); + + /** + * \brief Required by framework to get hold of the GUI. + * \return QWidget* the top most QWidget for the GUI. + */ + QWidget* GetQtControl() const; + + /** + * \see IPreferencePage::PerformOk + */ + virtual bool PerformOk(); + + /** + * \see IPreferencePage::PerformCancel + */ + virtual void PerformCancel(); + + /** + * \see IPreferencePage::Update + */ + virtual void Update(); + + public slots: + +protected: + + QWidget *m_MainControl; + Ui::RTUIPreferencePageControls* m_Controls; + + berry::IPreferences::Pointer m_PreferencesNode; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePageControls.ui b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePageControls.ui new file mode 100644 index 0000000000..efd18081ca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTUIPreferencePageControls.ui @@ -0,0 +1,86 @@ + + + RTUIPreferencePageControls + + + + 0 + 0 + 403 + 438 + + + + Form + + + + + + Handling of unkown prescribed dose: + + + + + + false + + + % + + + 200.000000000000000 + + + 80.000000000000000 + + + + + + + set to default value: + + + + + + + set relative to max dose: + + + + + + + Gy + + + 9999.000000000000000 + + + 50.000000000000000 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp new file mode 100644 index 0000000000..b3d5f0f077 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp @@ -0,0 +1,245 @@ +/*=================================================================== + +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 "mitkDoseVisPreferenceHelper.h" +#include "mitkRTUIConstants.h" +#include "mitkIsoLevelsGenerator.h" + + +#include + +#include + +#include +#include + +void mitk::StorePresetsMap(const PresetMapType& presetMap) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer doseVisNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + berry::IPreferences::Pointer presetsNode = doseVisNode->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + presetsNode->RemoveNode(); + doseVisNode->Flush(); + + //new empty preset node + presetsNode = doseVisNode->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + //store map in new node + for (PresetMapType::const_iterator pos = presetMap.begin(); pos != presetMap.end(); ++pos) + { + berry::IPreferences::Pointer aPresetNode = presetsNode->Node(pos->first); + + unsigned int id = 0; + + for (mitk::IsoDoseLevelSet::ConstIterator levelPos = pos->second->Begin(); levelPos != pos->second->End(); ++levelPos, ++id ) + { + std::ostringstream stream; + stream << id; + + berry::IPreferences::Pointer levelNode = aPresetNode->Node(stream.str()); + + levelNode->PutDouble(mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID,levelPos->GetDoseValue()); + levelNode->PutFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID,levelPos->GetColor().GetRed()); + levelNode->PutFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID,levelPos->GetColor().GetGreen()); + levelNode->PutFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID,levelPos->GetColor().GetBlue()); + levelNode->PutBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID,levelPos->GetVisibleIsoLine()); + levelNode->PutBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID,levelPos->GetVisibleColorWash()); + levelNode->Flush(); + } + + aPresetNode->Flush(); + } + + presetsNode->Flush(); +} + +mitk::PresetMapType mitk::LoadPresetsMap() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer presetsNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + typedef std::vector NamesType; + NamesType names = presetsNode->ChildrenNames(); + + PresetMapType presetMap; + + for (NamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + berry::IPreferences::Pointer aPresetNode = presetsNode->Node(*pos); + + if (aPresetNode.IsNull()) + { + mitkThrow()<< "Error in preference interface. Cannot find preset node under given name. Name: "<<*pos; + } + + mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); + + NamesType levelNames = aPresetNode->ChildrenNames(); + for (NamesType::const_iterator levelName = levelNames.begin(); levelName != levelNames.end(); ++levelName) + { + berry::IPreferences::Pointer levelNode = aPresetNode->Node(*levelName); + if (aPresetNode.IsNull()) + { + mitkThrow()<< "Error in preference interface. Cannot find level node under given preset name. Name: "<<*pos<<"; Level id: "<<*levelName; + } + + mitk::IsoDoseLevel::Pointer isoLevel = mitk::IsoDoseLevel::New(); + + isoLevel->SetDoseValue(levelNode->GetDouble(mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID,0.0)); + mitk::IsoDoseLevel::ColorType color; + color.SetRed(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID,1.0)); + color.SetGreen(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID,1.0)); + color.SetBlue(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID,1.0)); + isoLevel->SetColor(color); + isoLevel->SetVisibleIsoLine(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID,true)); + isoLevel->SetVisibleColorWash(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID,true)); + + levelSet->SetIsoDoseLevel(isoLevel); + } + + presetMap.insert(std::make_pair(*pos,levelSet)); + } + + if (presetMap.size() == 0) + { //if there are no presets use fallback and store it. + presetMap = mitk::GenerateDefaultPresetsMap(); + StorePresetsMap(presetMap); + } + + return presetMap; +} + +mitk::PresetMapType mitk::GenerateDefaultPresetsMap() +{ + mitk::PresetMapType result; + + result.insert(std::make_pair(std::string("Virtuos"), mitk::GeneratIsoLevels_Virtuos())); + return result; +} + +std::string mitk::GetSelectedPresetName() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + std::string result = prefNode->Get(mitk::RTUIConstants::SELECTED_ISO_PRESET_ID, ""); + + return result; +} + +void mitk::SetSelectedPresetName(const std::string& presetName) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + berry::IPreferences::Pointer presetsNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + typedef std::vector NamesType; + NamesType presetNames = presetsNode->ChildrenNames(); + + NamesType::iterator finding = std::find(presetNames.begin(),presetNames.end(),presetName); + + if (finding == presetNames.end()) + { + mitkThrow()<< "Error. Tried to set invalid selected preset name. Preset name does not exist in the defined presets. Preset name: "<Put(mitk::RTUIConstants::SELECTED_ISO_PRESET_ID,presetName); +} + +bool mitk::GetReferenceDoseValue(mitk::DoseValueAbs& value) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + bool result = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, true); + value = prefNode->GetDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID, mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE); + + return result; +} + +void mitk::SetReferenceDoseValue(bool globalSync, mitk::DoseValueAbs value) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::RTUIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, globalSync); + if (value >= 0) + { + prefNode->PutDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID, value); + } +} + + +bool mitk::GetDoseDisplayAbsolute() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + bool result = prefNode->GetBool(mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID, false); + + return result; +} + +void mitk::SetDoseDisplayAbsolute(bool isAbsolute) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::RTUIConstants::DOSE_DISPLAY_ABSOLUTE_ID, isAbsolute); +} + +void mitk::SignalReferenceDoseChange(bool globalSync, mitk::DoseValueAbs value, ctkPluginContext* context) +{ + ctkServiceReference ref = context->getServiceReference(); + if (ref) + { + ctkEventAdmin* eventAdmin = context->getService(ref); + ctkProperties props; + props["value"] = value; + props["globalSync"] = globalSync; + ctkEvent presetMapChangedEvent(mitk::RTCTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED.c_str()); + eventAdmin->sendEvent(presetMapChangedEvent); + } +} + +void mitk::SignalPresetMapChange(ctkPluginContext* context) +{ + ctkServiceReference ref = context->getServiceReference(); + if (ref) + { + ctkEventAdmin* eventAdmin = context->getService(ref); + ctkEvent presetMapChangedEvent(mitk::RTCTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED.c_str()); + eventAdmin->sendEvent(presetMapChangedEvent); + } +} diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h new file mode 100644 index 0000000000..6f5a9d8eed --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h @@ -0,0 +1,70 @@ +/*=================================================================== + +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 __DOSE_VIS_PREFERENCE_HELPER_H +#define __DOSE_VIS_PREFERENCE_HELPER_H + +#include +#include + +#include "mitkIsoDoseLevelCollections.h" + +class ctkPluginContext; + +namespace mitk +{ + typedef std::map PresetMapType; + + /** Stores the given preset map in the application preferences. */ + void StorePresetsMap(const PresetMapType& presetMap); + + /** Loads all defined iso dose level presets from the preferences and stores them + in a map. Key is the name of the preset. + @remark If no presets are stored in the preferences this function will generate default presets + (using GenerateDefaultPresetsMap()) and the stores it in the preferences (to guarantee a consistent state) + before passing the default presets back.*/ + PresetMapType LoadPresetsMap(); + + /** Generate the default presets map.*/ + PresetMapType GenerateDefaultPresetsMap(); + + /**Retrieves the name of the preset, that is currently selected for the application, from the preferences.*/ + std::string GetSelectedPresetName(); + + /** checks if the passed name exists in the preset map. If not an exception is thrown. If it exists, the new + * value will be set.*/ + void SetSelectedPresetName(const std::string& presetName); + + /** retrieves the reference dose from the preferences and indicates if global sync for reference dose is activated + or not. + @param value The reference dose value stored in the preferences. + @return Indicator for global sync. True: global sync activated -> preference value is relevant. + False: global sync deactivated. Value is irrelevant. Each node has its own value.*/ + bool GetReferenceDoseValue(DoseValueAbs& value); + /** Sets the global sync setting and dose reference value in the preferences. + * @param globalSync Indicator if global sync should be set active (true) or inactive (false). If it is true, the value is irrelevant (but will be set). + * @param value The dose reference value that should be stored in the preferences.If set to <0 it will be ignored and not changed/set.*/ + void SetReferenceDoseValue(bool globalSync, DoseValueAbs value = -1); + + bool GetDoseDisplayAbsolute(); + void SetDoseDisplayAbsolute(bool isAbsolute); + + void SignalReferenceDoseChange(bool globalSync, mitk::DoseValueAbs value, ctkPluginContext* context); + void SignalPresetMapChange(ctkPluginContext* context); +} + +#endif diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.cpp b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.cpp new file mode 100644 index 0000000000..e54ffd0a39 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.cpp @@ -0,0 +1,53 @@ +/*=================================================================== + +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 "org_mitk_gui_qt_dosevisualization_Activator.h" + +#include + +#include "RTDoseVisualizer.h" +#include "RTUIPreferencePage.h" +#include "DoseVisualizationPreferencePage.h" + +namespace mitk { + + ctkPluginContext* org_mitk_gui_qt_dosevisualization_Activator::m_Context = NULL; + + void org_mitk_gui_qt_dosevisualization_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(RTDoseVisualizer, context); + BERRY_REGISTER_EXTENSION_CLASS(RTUIPreferencePage, context) + BERRY_REGISTER_EXTENSION_CLASS(DoseVisualizationPreferencePage, context) + + m_Context = context; + } + + void org_mitk_gui_qt_dosevisualization_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + + m_Context = NULL; + } + + ctkPluginContext* org_mitk_gui_qt_dosevisualization_Activator::GetContext() + { + return m_Context; + } + +} + +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_dosevisualization, mitk::org_mitk_gui_qt_dosevisualization_Activator) diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.h new file mode 100644 index 0000000000..b0429a4beb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/org_mitk_gui_qt_dosevisualization_Activator.h @@ -0,0 +1,46 @@ +/*=================================================================== + +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 org_mitk_gui_qt_dosevisualization_Activator_h +#define org_mitk_gui_qt_dosevisualization_Activator_h + +#include + +namespace mitk { + + class org_mitk_gui_qt_dosevisualization_Activator : + public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_INTERFACES(ctkPluginActivator) + + public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + + static ctkPluginContext* GetContext(); + + private: + + static ctkPluginContext* m_Context; + + }; // org_mitk_gui_qt_dosevisualization_Activator + +} + +#endif // org_mitk_gui_qt_dosevisualization_Activator_h