914 lines
22 KiB
C++
914 lines
22 KiB
C++
#include "view/DicomImageView.h"
|
|
//#include <DcmFile.h>
|
|
//#include <DcmDataset.h>
|
|
//#include "view/subview/metaDataWindow.h"
|
|
#include <QMessageBox>
|
|
#include <QDebug>
|
|
#include <QMimeData>
|
|
#include "view/thumbnailImage.h"
|
|
#include <vtkInteractorStyleImage.h>
|
|
#include "vtkImageProperty.h"
|
|
#include "view/subview/mytitlebar.h"
|
|
|
|
#include "ActorDraggableInteractorStyle.h"
|
|
#include "pqVCRController.h"
|
|
#include "pqVCRToolbar.h"
|
|
#include "vtkDiscretizableColorTransferFunction.h"
|
|
#include "metaDataWindow.h"
|
|
|
|
#include "include_dcmtk.h"
|
|
//-----------------------------------------------------------------------------
|
|
DicomImageView::DicomImageView(QWidget* parent)
|
|
: QFrame(parent)
|
|
{
|
|
|
|
QFrame *wrapper = new QFrame(this);
|
|
wrapper->setObjectName("wrapper");
|
|
|
|
QGridLayout *view_layout = new QGridLayout(this);
|
|
_titleBar = createMyTitleBar();
|
|
view_layout->addWidget(_titleBar, 0, 0);
|
|
view_layout->addWidget(wrapper, 1, 0);
|
|
view_layout->setContentsMargins(0, 0, 0, 0);
|
|
view_layout->setSpacing(0);
|
|
this->setLayout(view_layout);
|
|
|
|
|
|
QGridLayout* controlLayout = new QGridLayout(wrapper);
|
|
|
|
_glWidt = new QVTKOpenGLNativeWidget(wrapper);
|
|
|
|
m_glrenWin = vtkSmartPointer <vtkGenericOpenGLRenderWindow>::New();
|
|
//m_glrenWin->SetOffScreenRendering(1); //for offscreen rendering
|
|
_glWidt->SetRenderWindow(m_glrenWin);//set up interacte
|
|
//in order to visit in both way!
|
|
// _glWidt->SetImageView(this);
|
|
|
|
controlLayout->addWidget(_glWidt, 0, 0);
|
|
|
|
|
|
_scrollBar = new QScrollBar(Qt::Orientation::Vertical);
|
|
_scrollBar->setFocusPolicy(Qt::StrongFocus);
|
|
_scrollBar->setVisible(false);
|
|
_scrollBar->setObjectName("scrollbar");
|
|
|
|
|
|
|
|
|
|
controlLayout->addWidget(_scrollBar, 0, 1);
|
|
|
|
controlLayout->setContentsMargins(0, 0, 0, 0);
|
|
controlLayout->setSpacing(0);
|
|
wrapper->setLayout(controlLayout);
|
|
//this->setLayout(controlLayout);
|
|
|
|
setAutoFillBackground(true);
|
|
|
|
QWidget::setAcceptDrops(true);
|
|
this->setObjectName("dicomview");
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
DicomImageView::~DicomImageView()
|
|
{
|
|
_thread.quit();//event loop
|
|
_thread.wait(); //wait until return,block mode
|
|
_vcr_toolbar->deleteLater();
|
|
}
|
|
|
|
|
|
bool DicomImageView::isVCRVisible()
|
|
{
|
|
return _vcr_toolbar->isVisible();
|
|
}
|
|
|
|
void DicomImageView::setVCRVisible(bool visible)
|
|
{
|
|
_vcr_toolbar->setVisible(visible);
|
|
}
|
|
void DicomImageView::cineModeOn()
|
|
{
|
|
//updateVCRToolbarPos();
|
|
int ax = (this->geometry().bottomLeft().x() + this->geometry().bottomRight().x()) / 2 + VCRHelper::getVCRXOffset();
|
|
int ay = (this->geometry().bottomLeft().y() + this->geometry().bottomRight().y()) / 2 + VCRHelper::getVCRYOffset();
|
|
_vcr_toolbar->move(ax, ay);
|
|
|
|
_vcr_toolbar->show();
|
|
this->initCineModeThread();
|
|
_vcr_toolbar->reConnectController(_vcr_ctrl);
|
|
|
|
}
|
|
|
|
void DicomImageView::initCineModeThread()
|
|
{
|
|
_vcr_ctrl = new pqVCRController(nullptr, this);
|
|
_vcr_ctrl->moveToThread(&_thread);
|
|
connect(&_thread, &QThread::finished, _vcr_ctrl, &QObject::deleteLater);
|
|
_thread.start();
|
|
isCine = true;
|
|
}
|
|
|
|
|
|
MyTitleBar * DicomImageView::createMyTitleBar()
|
|
{
|
|
MyTitleBar *titleBar = new MyTitleBar(this);
|
|
connect(titleBar, &MyTitleBar::signalButtonMaxClicked, this, &DicomImageView::Slot_viewDoubleclicked);
|
|
connect(titleBar, &MyTitleBar::signalButtonCloseClicked, this, &DicomImageView::Slot_ViewEmpty);
|
|
return titleBar;
|
|
}
|
|
|
|
|
|
void DicomImageView::AddSlice(int step)
|
|
{
|
|
if (_ImageViewer == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
if (HasSeries())
|
|
{
|
|
int curSlice = _ImageViewer->GetSlice() + step;
|
|
_ImageViewer->SetSlice(curSlice);
|
|
_scrollBar->setValue(curSlice);
|
|
}
|
|
}
|
|
|
|
void DicomImageView::onFirstFrame()
|
|
{
|
|
if (HasSeries()) {
|
|
_scrollBar->setValue(_ImageViewer->GetSliceMin());
|
|
}
|
|
}
|
|
void DicomImageView::onPreviousFrame()
|
|
{
|
|
if (HasSeries()) {
|
|
int slice = _ImageViewer->GetSlice();
|
|
slice = slice--;
|
|
int min_slice = _ImageViewer->GetSliceMin();
|
|
if (slice < min_slice)
|
|
{
|
|
slice = _ImageViewer->GetSliceMax();
|
|
}
|
|
_scrollBar->setValue(slice);
|
|
}
|
|
}
|
|
void DicomImageView::onNextFrame()
|
|
{
|
|
if (HasSeries()) {
|
|
int slice = _ImageViewer->GetSlice();
|
|
slice = slice++;
|
|
int max_slice = _ImageViewer->GetSliceMax();
|
|
if (slice > max_slice)
|
|
{
|
|
slice = _ImageViewer->GetSliceMin();
|
|
}
|
|
_scrollBar->setValue(slice);
|
|
}
|
|
}
|
|
void DicomImageView::onLastFrame()
|
|
{
|
|
if (HasSeries()) {
|
|
_scrollBar->setValue(_ImageViewer->GetSliceMax());
|
|
}
|
|
}
|
|
|
|
void DicomImageView::SetSlice(int slice)
|
|
{
|
|
if (_ImageViewer == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
if (HasSeries())
|
|
{
|
|
|
|
_ImageViewer->SetSlice(slice);
|
|
//_ImageViewer->updateCornerInfo(TOP_LEFT);
|
|
_scrollBar->setValue(slice);
|
|
}
|
|
}
|
|
|
|
|
|
void DicomImageView::Slot_scrollValueChanged(int slice)
|
|
{
|
|
//if the scroll bar is activated by user, emit
|
|
//if the scroll bar is activated by program, no emit
|
|
switch (_ScrollTriggerType)
|
|
{
|
|
case(scrollScope::TriggerType::USER_TRIGGER):
|
|
{
|
|
_ImageViewer->SetSlice(slice); //for interactor style use, reduce duplicate
|
|
// no break;
|
|
}
|
|
case(scrollScope::TriggerType::STYLE_TRIGGER):
|
|
{
|
|
_ImageViewer->updateCornerInfo(TOP_LEFT);
|
|
//invoke event
|
|
_SliceStep = slice - _PrevSlice;
|
|
_PrevSlice = slice;
|
|
//emit Signal_scrollValueChanged(this, slice);
|
|
int sliceArray[2];
|
|
sliceArray[0] = slice;
|
|
sliceArray[1] = _SliceStep;
|
|
|
|
this->Signal_SyncEvent(this, VTKIS_IMAGE_SLICING, sliceArray);
|
|
break;
|
|
}
|
|
case(scrollScope::TriggerType::SYNC_ONLY):
|
|
{
|
|
_PrevSlice = slice;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
void DicomImageView::updateCornerInfoPrivacy()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
_ImageViewer->updateCornerInfo(TOP_RIGHT);
|
|
}
|
|
}
|
|
void DicomImageView::wheelEvent(QWheelEvent *event)
|
|
{
|
|
if (HasSeries()) {
|
|
int _Slice = _ImageViewer->GetSlice();
|
|
int _MinSlice = _ImageViewer->GetSliceMin();
|
|
int _MaxSlice = _ImageViewer->GetSliceMax();
|
|
|
|
if (event->delta() > 0)
|
|
{
|
|
//
|
|
//cout << "scroll forward" << endl;
|
|
if (_Slice > _MinSlice)
|
|
{
|
|
_Slice -= 1;
|
|
|
|
//this->SetSlice(_Slice);
|
|
_scrollBar->setValue(_Slice);
|
|
|
|
//emit Signal_scrollValueChanged(this, _Slice);
|
|
//emit scroll_ValueChanged(_Slice);
|
|
//mySetSlice(_Slice);
|
|
}
|
|
else
|
|
{
|
|
_Slice = _MinSlice;
|
|
//this->SetSlice(_Slice);
|
|
_scrollBar->setValue(_Slice);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
//cout << "scroll backward" << endl;
|
|
if (_Slice < _MaxSlice)
|
|
{
|
|
_Slice += 1;
|
|
//this->SetSlice(_Slice);
|
|
_scrollBar->setValue(_Slice);
|
|
//emit Signal_scrollValueChanged(this, _Slice);
|
|
//emit scroll_ValueChanged(_Slice);
|
|
//mySetSlice(_Slice);
|
|
}
|
|
else
|
|
{
|
|
_Slice = _MaxSlice;
|
|
//this->SetSlice(_Slice);
|
|
_scrollBar->setValue(_Slice);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void DicomImageView::Slot_ViewEmpty()
|
|
{
|
|
emit Signal_ViewEmpty(this);
|
|
}
|
|
|
|
|
|
////-----------------------------------------------------------------------------
|
|
void DicomImageView::mousePressEvent(QMouseEvent* event)
|
|
{
|
|
|
|
emit Signal_ViewClicked(this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void DicomImageView::mouseMoveEvent(QMouseEvent* event)
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void DicomImageView::mouseReleaseEvent(QMouseEvent* event)
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void DicomImageView::mouseDoubleClickEvent(QMouseEvent* event)
|
|
{
|
|
//Slot_viewDoubleclicked();
|
|
}
|
|
void DicomImageView::Slot_viewDoubleclicked()
|
|
{
|
|
//emit Signal_ViewClicked(this);
|
|
emit Signal_viewDoubleclicked(this);
|
|
}
|
|
//-------------------------------------------------------
|
|
/**
|
|
* @brief DicomImageView::dragEnterEvent
|
|
* 拖拽进入
|
|
* @param e
|
|
*/
|
|
void DicomImageView::dragEnterEvent(QDragEnterEvent *e) {
|
|
if (e->mimeData()->hasFormat("text/plain")) {
|
|
e->acceptProposedAction();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
/**
|
|
* @brief DicomImageView::dragMoveEvent
|
|
* 拖拽移动
|
|
* @param e
|
|
*/
|
|
void DicomImageView::dragMoveEvent(QDragMoveEvent *e) {
|
|
if (e->mimeData()->hasFormat("text/plain")) {
|
|
e->acceptProposedAction();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
/**
|
|
* @brief DicomImageView::dropEvent
|
|
* 拖拽松开
|
|
* @param e
|
|
*/
|
|
void DicomImageView::dropEvent(QDropEvent *e) {
|
|
if (e->mimeData()->hasFormat("text/plain")) {
|
|
e->acceptProposedAction();
|
|
thumbnailImage *tb = qobject_cast<thumbnailImage*>(
|
|
(QObject *)(e->mimeData()->text().toULongLong()));
|
|
if (tb) {
|
|
//SetSeriesInstance(s);
|
|
//this->UpdataSeriesInstance();
|
|
emit Signal_DragDropEvent(this, tb);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------
|
|
/**
|
|
* @brief DicomImageView::dragLeaveEvent
|
|
* 离开事件
|
|
* @param e
|
|
*/
|
|
void DicomImageView::dragLeaveEvent(QDragLeaveEvent *) {
|
|
return;
|
|
}
|
|
|
|
void DicomImageView::getWindowLevel(double &level, double &width)
|
|
{
|
|
if (HasSeries()) {
|
|
//_Series->getWindowLevel(level, width);
|
|
level = _ImageViewer->GetColorLevel();
|
|
width = _ImageViewer->GetColorWindow();
|
|
}
|
|
|
|
}
|
|
|
|
void DicomImageView::ToggleNegativeMode()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
if (isNegative)
|
|
{
|
|
_ImageViewer->SetNegativeMode(false);
|
|
isNegative = false;
|
|
}
|
|
else
|
|
{
|
|
_ImageViewer->SetNegativeMode(true);
|
|
isNegative = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void DicomImageView::setWindowLevel(double level, double width)
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
|
|
_ImageViewer->SetColorLevel(level);
|
|
_ImageViewer->SetColorWindow(width);
|
|
//You have to call updateConerInfo manually
|
|
//only mouse event can rely on callback
|
|
_ImageViewer->updateCornerInfo(BOTTOM_RIGHT);
|
|
emit Signal_WindowLevelEventForFusion(level, width);
|
|
|
|
}
|
|
}
|
|
|
|
void DicomImageView::initScrollbar()
|
|
{
|
|
//_MinSlice = _ImageViewer->GetSliceMin();
|
|
//_MaxSlice = _ImageViewer->GetSliceMax();
|
|
_scrollBar->setValue(_ImageViewer->GetSliceMin());
|
|
_scrollBar->setMaximum(_ImageViewer->GetSliceMax());
|
|
_scrollBar->setSingleStep(1);
|
|
_scrollBar->setVisible(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
void DicomImageView::ResetPanZoom()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
//necessary to reset pan
|
|
_ImageViewer->GetRenderer()->ResetCamera();
|
|
//necessary to reset zoom
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->SetParallelScale(_Series->GetExtent());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void DicomImageView::ClearTransformations()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
int slice = _ImageViewer->GetSlice();
|
|
ResetPanZoom();
|
|
|
|
double cameraPosition[3];
|
|
double vup[3];
|
|
_Series->getCameraCfg(vup, cameraPosition);
|
|
|
|
//necessary to reset flip and rotate
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->SetPosition(cameraPosition);
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->SetViewUp(vup);
|
|
//avoid black out problem
|
|
_ImageViewer->GetRenderer()->ResetCameraClippingRange();
|
|
_ImageViewer->SetSlice(slice);
|
|
//Render
|
|
_ImageViewer->GetRenderWindow()->Render();
|
|
emit Signal_Transformation(CLEAR);
|
|
}
|
|
}
|
|
|
|
void DicomImageView::HFlip()
|
|
{
|
|
if (HasSeries()) {
|
|
int slice = _ImageViewer->GetSlice();
|
|
ResetPanZoom();
|
|
//HFlip
|
|
//_ImageViewer->GetRenderer()->GetActiveCamera()->SetViewUp(0, 1, 0);
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->Azimuth(180);
|
|
FlipExportHelper::toggleFlip();
|
|
//to avoid black out problem during slicing
|
|
//slicing is related with rotation, you have to recalculate to get it right
|
|
_ImageViewer->GetRenderer()->ResetCameraClippingRange();
|
|
_ImageViewer->SetSlice(slice);
|
|
|
|
_ImageViewer->GetRenderWindow()->Render();
|
|
emit Signal_Transformation(H_FLIP);
|
|
}
|
|
}
|
|
|
|
|
|
void DicomImageView::VFlip()
|
|
{
|
|
if (HasSeries()) {
|
|
//double scale = _ImageViewer->GetRenderer()->GetActiveCamera()->GetParallelScale();
|
|
|
|
int slice = _ImageViewer->GetSlice();
|
|
ResetPanZoom();
|
|
//Method 2: Order matters
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->Elevation(-180);
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->Roll(180);
|
|
//_ImageViewer->GetRenderer()->GetActiveCamera()->SetViewUp(0,-1,0);
|
|
FlipExportHelper::toggleFlip();
|
|
//to avoid black out problem during slicing
|
|
//slicing is related with rotation, you have to recalculate to get it right
|
|
|
|
_ImageViewer->GetRenderer()->ResetCameraClippingRange();
|
|
_ImageViewer->SetSlice(slice);
|
|
_ImageViewer->GetRenderWindow()->Render();
|
|
emit Signal_Transformation(V_FLIP);
|
|
}
|
|
|
|
}
|
|
void DicomImageView::Rotate(double angle, TransFormType operation)
|
|
{
|
|
if (HasSeries()) {
|
|
int slice = _ImageViewer->GetSlice();
|
|
ResetPanZoom();
|
|
_ImageViewer->GetRenderer()->GetActiveCamera()->Roll(angle);
|
|
//to avoid black out problem during slicing
|
|
//slcing is related with rotation, you have to recalculate to get it right
|
|
_ImageViewer->GetRenderer()->ResetCameraClippingRange();
|
|
_ImageViewer->SetSlice(slice);
|
|
_ImageViewer->GetRenderWindow()->Render();
|
|
emit Signal_Transformation(operation);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//NOTE: not working
|
|
void DicomImageView::setHighlight(bool yes) {
|
|
_titleBar->SetHighlight(yes);
|
|
|
|
}
|
|
bool DicomImageView::IsFusion()
|
|
{
|
|
return _ImageViewer->GetFusion();
|
|
|
|
}
|
|
void DicomImageView::SetFusionInput(DicomImageView *overlay)
|
|
{
|
|
_overlay = overlay;
|
|
|
|
vtkImageData *overlay_data = _overlay->getSeriesInstance()->GetData();
|
|
|
|
double window;
|
|
double level;
|
|
_overlay->getWindowLevel(level, window);
|
|
|
|
_ImageViewer->FusionOn();
|
|
_overlay->OverlayOn();
|
|
_overlay->SetBaseView(this);
|
|
|
|
_ImageViewer->SetFusionInputData(overlay_data);
|
|
_ImageViewer->SetFusionColorLeveL(level);
|
|
_ImageViewer->SetFusionColorWindow(window);
|
|
_ImageViewer->SetFusionOpacity(_ImageViewer->GetFusionOpacity());
|
|
|
|
// Example for vtkDiscretizableColorTransferFunction
|
|
vtkNew< vtkDiscretizableColorTransferFunction> table;
|
|
// example table1 d->r->g->w
|
|
table->AddRGBPoint(0.0, 0.0, 0.0, 0.0);
|
|
table->AddRGBPoint(0.33, 1.0, 0.0, 0.0);
|
|
table->AddRGBPoint(0.66, 1.0, 1.0, 0.0);
|
|
table->AddRGBPoint(1.0, 1.0, 1.0, 1.0);
|
|
_ImageViewer->SetFusionColorTable(table);
|
|
|
|
}
|
|
|
|
void DicomImageView::Slot_WindowLevelEventForFusion(double level, double width)
|
|
{
|
|
if (IsFusion()) {
|
|
_ImageViewer->SetFusionColorLeveL(level);
|
|
_ImageViewer->SetFusionColorWindow(width);
|
|
_ImageViewer->Render();
|
|
}
|
|
}
|
|
|
|
void DicomImageView::IncreFusionOpacity(double percent) {
|
|
if (IsFusion()) {
|
|
_ImageViewer->IncreFusionOpacity(percent);
|
|
_ImageViewer->Render();
|
|
}
|
|
}
|
|
|
|
//@{
|
|
/**
|
|
* Remove Fusion no matter it is base or overlay
|
|
*/
|
|
void DicomImageView::removeViewWithFusion()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
if (IsFusion()) {
|
|
disconnect(_overlay, &DicomImageView::Signal_WindowLevelEventForFusion,
|
|
this, &DicomImageView::Slot_WindowLevelEventForFusion);
|
|
|
|
this->removeFusion();
|
|
_overlay->SetBaseView(nullptr);
|
|
_overlay = nullptr;
|
|
}
|
|
|
|
if (IsOverlay()) {
|
|
disconnect(this, &DicomImageView::Signal_WindowLevelEventForFusion,
|
|
_base, &DicomImageView::Slot_WindowLevelEventForFusion);
|
|
|
|
_base->removeFusion();
|
|
_base->SetOverlayView(nullptr);
|
|
_base = nullptr;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void DicomImageView::removeFusion()
|
|
{
|
|
_ImageViewer->RemoveFusionData();
|
|
_ImageViewer->FusionOff();
|
|
_ImageViewer->Render();
|
|
_overlay->OverlayOff();
|
|
}
|
|
|
|
void DicomImageView::ActiveMeasure(Measure *m)
|
|
{
|
|
if (nullptr != _Series)
|
|
{
|
|
_ImageViewer->ActiveMeasure(m);
|
|
}
|
|
}
|
|
|
|
void DicomImageView::DeleteSelectedMeasure()
|
|
{
|
|
if (nullptr != _Series)
|
|
{
|
|
_ImageViewer->DeleteSelectedMeasure();
|
|
}
|
|
}
|
|
void DicomImageView::DeleteCurrentSliceMeasure()
|
|
{
|
|
if (nullptr != _Series)
|
|
{
|
|
_ImageViewer->DeleteCurrentSliceMeasure();
|
|
}
|
|
}
|
|
void DicomImageView::DeleteCurrentSeriesMeasure()
|
|
{
|
|
if (nullptr != _Series)
|
|
{
|
|
_ImageViewer->DeleteCurrentSeriesMeasure();
|
|
}
|
|
}
|
|
void DicomImageView::removeViewWithMeasure()
|
|
{
|
|
_ImageViewer->UnActiveMeasure();
|
|
_ImageViewer->DeleteCurrentSeriesMeasure();
|
|
}
|
|
|
|
|
|
|
|
void DicomImageView::setDicomImageView(SeriesInstance *series)
|
|
{
|
|
//series->setVTKOpenGLNativeWidget(this->_glView);
|
|
CopyFromSeries(series);
|
|
//whenver change instance,set scroll value to zero
|
|
initScrollbar();
|
|
|
|
connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(Slot_scrollValueChanged(int)));
|
|
connect(this, SIGNAL(Signal_Transformation(TransFormType)), this, SLOT(Slot_UpdateOrienInfo(TransFormType)));
|
|
}
|
|
|
|
bool DicomImageView::HasSeries()
|
|
{
|
|
if (nullptr == _Series)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
void DicomImageView::Render()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
//_Series->Render();
|
|
if (_ImageViewer->GetvtkCornerAnnotation()) {
|
|
_ImageViewer->GetvtkCornerAnnotation()->SetMaximumFontSize(FontSizeHelper::getSize(frameGeometry().size()));
|
|
}
|
|
_ImageViewer->Render();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void DicomImageView::CopyFromSeries(SeriesInstance *series)
|
|
{
|
|
_Series = series;
|
|
_ImageViewer = series->getImageViewer2();
|
|
//_CornerAnno = _ImageViewer->GetvtkCornerAnnotation();
|
|
|
|
|
|
//create some callbacks
|
|
//m_syncEventCallback = vtkCallbackCommand::New();
|
|
//m_syncEventCallback->SetCallback(syncEventFunc);
|
|
//m_syncEventCallback->SetClientData(this);
|
|
|
|
ActorDraggableInteractorStyle *style = _ImageViewer->GetInteractorStyle();
|
|
style->AddObserver(vtkCommand::EventIds::EndPanEvent, this, &DicomImageView::syncEventFunc);
|
|
//style->AddObserver(vtkCommand::EventIds::EndRotateEvent, this, &DicomImageView::syncEventFunc);
|
|
style->AddObserver(vtkCommand::EventIds::EndWindowLevelEvent, this, &DicomImageView::syncEventFunc);
|
|
style->AddObserver(ActorDraggableInteractorStyle::DraggableStyleEvents::EndDollyEvent, this, &DicomImageView::syncEventFunc);
|
|
style->AddObserver(ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent, this, &DicomImageView::syncEventFunc);
|
|
style->AddObserver(vtkCommand::EventIds::WindowLevelEvent, this, &DicomImageView::updateWindowLevelCb);
|
|
style->AddObserver(ActorDraggableInteractorStyle::DoubleClickEvent, this, &DicomImageView::doubleclickedEventCb);
|
|
style->AddObserver(ActorDraggableInteractorStyle::ScalarOpacityEvent, this, &DicomImageView::scalarEventCb);
|
|
style->AddObserver(ActorDraggableInteractorStyle::ScalarShiftEvent, this, &DicomImageView::scalarEventCb);
|
|
}
|
|
|
|
void DicomImageView::updateWindowLevelCb(vtkObject*caller, unsigned long eid, void *calldata)
|
|
{
|
|
_ImageViewer->updateCornerInfo(BOTTOM_RIGHT);
|
|
emit Signal_WindowLevelEventForFusion(_ImageViewer->GetColorLevel(), _ImageViewer->GetColorWindow());
|
|
}
|
|
|
|
|
|
|
|
void DicomImageView::scalarEventCb(vtkObject* sender, unsigned long eventId, void* calldata)
|
|
{
|
|
double* r = (double*)calldata;
|
|
switch (eventId)
|
|
{
|
|
case(ActorDraggableInteractorStyle::ScalarShiftEvent):
|
|
qDebug() << "ScalarShiftEvent";
|
|
_ImageViewer->SwitchToNextPreset();
|
|
|
|
break;
|
|
case(ActorDraggableInteractorStyle::ScalarOpacityEvent):
|
|
qDebug() << "ScalarOpacityEvent" << r[0];
|
|
IncreFusionOpacity(r[0]);
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
}
|
|
void DicomImageView::doubleclickedEventCb(vtkObject* sender, unsigned long eventId, void* calldata) {
|
|
emit Signal_viewDoubleclicked(this);
|
|
}
|
|
|
|
void DicomImageView::syncEventFunc(vtkObject*caller, unsigned long eid, void *calldata)
|
|
{
|
|
|
|
int* r = (int*)calldata;
|
|
switch (eid)
|
|
{
|
|
case(vtkCommand::EventIds::EndPanEvent):
|
|
this->Signal_SyncEvent(this, VTKIS_IMAGE_PAN, calldata);
|
|
break;
|
|
case(vtkCommand::EventIds::EndWindowLevelEvent):
|
|
//update corner info through callback
|
|
this->Signal_SyncEvent(this, VTKIS_IMAGE_WINDOWLEVEL, calldata);
|
|
break;
|
|
case(ActorDraggableInteractorStyle::DraggableStyleEvents::EndDollyEvent):
|
|
this->Signal_SyncEvent(this, VTKIS_IMAGE_ZOOM, calldata);
|
|
break;
|
|
case(ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent):
|
|
|
|
//_Series->updateConerInfo(TOP_LEFT);
|
|
//this->m_scrl_active = false;
|
|
//_scrollBar->setValue(r[0]);
|
|
//r[1] = _SliceStep; //must after slot scrollValueChanged
|
|
//this->m_scrl_active = true;
|
|
//this->Signal_ViewChanged(this, VTKIS_IMAGE_SLICING, calldata);
|
|
|
|
_scrollBar->setValue(r[0]);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
//void DicomImageView::syncPan(vtkObject*caller, unsigned long eid, void* clientdata, void *calldata)
|
|
//{
|
|
// DicomImageView *viewer = static_cast<DicomImageView*>(clientdata);
|
|
//
|
|
// //double level;
|
|
// //double width;
|
|
// //viewer->getWindowLevel(level, width);
|
|
// //viewer->Signal_WindowLevelChanged(viewer, level, width);
|
|
//}
|
|
|
|
void DicomImageView::orphanizeSeriesInstance()
|
|
{
|
|
//this will be the last instance ,only serve for copy
|
|
_ImageViewer->GetRenderer()->RemoveAllViewProps();
|
|
this->Render();
|
|
}
|
|
void DicomImageView::ResetView()
|
|
{
|
|
|
|
if (HasSeries())
|
|
{
|
|
|
|
removeViewWithFusion();
|
|
removeViewWithMeasure();
|
|
|
|
|
|
|
|
|
|
orphanizeSeriesInstance();
|
|
//_glWidt->update();
|
|
|
|
//_scrollBar = nullptr;
|
|
_ImageViewer = nullptr;
|
|
_Series = nullptr;
|
|
|
|
_ScrollTriggerType = scrollScope::TriggerType::USER_TRIGGER;
|
|
//_Slice = 0;
|
|
_PrevSlice = 0;
|
|
_SliceStep = 0;
|
|
|
|
}
|
|
|
|
_scrollBar->setVisible(false);
|
|
|
|
if (isCine)
|
|
{
|
|
_vcr_toolbar->setVisible(false);
|
|
}
|
|
}
|
|
int DicomImageView::getSeriesNumber()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
return _Series->GetSeriesNumber();
|
|
}
|
|
return -1;
|
|
}
|
|
void DicomImageView::updateCornerInfoAll()
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
_ImageViewer->updateCornerInfoAll();
|
|
}
|
|
}
|
|
void DicomImageView::ShowMetaData()
|
|
{
|
|
|
|
QString fileName = QString::fromLatin1(this->_Series->getCurImageName());
|
|
if (!fileName.isEmpty()) {
|
|
|
|
//DcmFileFormat *dcmFile = new DcmFileFormat;
|
|
DcmFileFormat dcmFile;
|
|
if (!dcmFile.loadFile(fileName.toStdString()).good())
|
|
{
|
|
QMessageBox::warning(this,
|
|
tr("Error"),
|
|
tr("Unable to read file %1").arg(fileName),
|
|
QMessageBox::Ok);
|
|
return;
|
|
}
|
|
//DcmDataset* dataset = dcmFile.getDataset();
|
|
metaDataWindow *dicomWindow = new metaDataWindow(&dcmFile);
|
|
dicomWindow->setAttribute(Qt::WA_DeleteOnClose);
|
|
dicomWindow->setWindowTitle("DICOM Tags ("+fileName+")");
|
|
dicomWindow->setWindowFilePath(fileName);
|
|
//dicomWindow->resize(dicomWindow->sizeHint());
|
|
dicomWindow->resize(USER_CONFIG::DEFAULT_TAG_WINDOW_SIZE);
|
|
//this->centralWidget->addSubWindow(dicomWindow);
|
|
dicomWindow->show();
|
|
|
|
}
|
|
}
|
|
|
|
void DicomImageView::resizeEvent(QResizeEvent *event)
|
|
{
|
|
//auto size conner info
|
|
if (!_ImageViewer) return;
|
|
if (_ImageViewer->GetvtkCornerAnnotation()) {
|
|
_ImageViewer->GetvtkCornerAnnotation()->SetMaximumFontSize(FontSizeHelper::getSize(frameGeometry().size()));
|
|
_ImageViewer->Render();
|
|
}
|
|
if (isCine)
|
|
{
|
|
//if (_vcr_toolbar->isVisible())
|
|
//we see the mountains as moutains,hh
|
|
{
|
|
int ax = (this->geometry().bottomLeft().x() + this->geometry().bottomRight().x()) / 2 + VCRHelper::getVCRXOffset();
|
|
int ay = (this->geometry().bottomLeft().y() + this->geometry().bottomRight().y()) / 2 + VCRHelper::getVCRYOffset();;
|
|
_vcr_toolbar->move(ax, ay);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void DicomImageView::SetZoomScale(double scale)
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
_ImageViewer->SetZoomScale(scale);
|
|
_ImageViewer->Render();
|
|
}
|
|
}
|
|
|
|
void DicomImageView::SetPanOffset(double * pan)
|
|
{
|
|
if (HasSeries())
|
|
{
|
|
|
|
_ImageViewer->SetPanOffset(pan);
|
|
_ImageViewer->Render();
|
|
}
|
|
}
|
|
|
|
|
|
void DicomImageView::Slot_UpdateOrienInfo(TransFormType operation)
|
|
{
|
|
_ImageViewer->updateOrienInfo(operation);
|
|
} |