Refactor dicomimageview and viewcontainerwidget.

This commit is contained in:
Krad
2022-07-06 09:32:56 +08:00
parent 9625835814
commit 6292db3b6c
6 changed files with 400 additions and 436 deletions

View File

@@ -1,9 +1,20 @@
// //
// Created by Krad on 2022/3/9. // Created by Krad on 2022/3/9.
// //
#include "ImageViewManager.h" #include "ImageViewManager.h"
#include "algorithm"
#include <algorithm>
#include <QPainter>
#include <QStyleOption>
#include <QMessageBox>
#include <QDebug>
#include <QVTKOpenGLNativeWidget.h>
#include "IO/DICOM/DicomLoader.h"
#include "Interaction/ActorDraggableInteractorStyle.h"
#include "UI/Widget/viewcontainerwidget.h"
#include "UI/Widget/thumbnailImage.h"
#include "UI/Widget/cine/pqVCRToolbar.h"
bool ImageViewManager::contains(DicomImageView *view) { bool ImageViewManager::contains(DicomImageView *view) {
auto iter = std::find(vList.begin(),vList.end(),view); auto iter = std::find(vList.begin(),vList.end(),view);
@@ -87,3 +98,67 @@ void ImageViewManager::smartDo(SmartDoCallback cb, DicomImageView *sourceView, v
}); });
} }
} }
//Slots and actions------------------------------------------------------------
void ViewContainerWidget::viewSynced(DicomImageView *view, int interactionMode, void *calldata) {
switch (interactionMode) {
case VTKIS_IMAGE_SLICING:
if (SyncHelper::getSyncItem(SLICE_POS)) {
if (SyncHelper::getSyncState() == AUTO_SYNC) {
mImageManager.smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double *r = (double *) callData;
v->syncSlicePoint(r);
v->SyncScrollBar();
}
}, view, calldata, ImageViewManager::EStudyEBoundsSeries);
}
if (SyncHelper::getSyncState() == MANUAL_SYNC) {
mImageManager.smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
//disable global trigger slot
int *r = (int *) callData;
v->addSlice(r[1]);
}
}, view, calldata, ImageViewManager::EStudyEBoundsSeries);
}
}
break;
case VTKIS_IMAGE_PAN:
if (SyncHelper::getSyncItem(ZOOM_PAN)) {
mImageManager.smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double *d = (double *) callData;
double vector[3] = {d[3] - d[0], d[4] - d[1], d[5] - d[2]};
v->setPanOffset(vector);
}
}, view, calldata, ImageViewManager::EStudyEBoundsSeries);
}
break;
case VTKIS_IMAGE_ZOOM:
if (SyncHelper::getSyncItem(ZOOM_PAN)) {
mImageManager.smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double *d = (double *) callData;
v->setZoomScale(d[1]);
}
}, view, calldata, ImageViewManager::EStudyEBoundsSeries);
}
break;
case VTKIS_IMAGE_WINDOWLEVEL:
if (SyncHelper::getSyncItem(WIDTH_LEVEL)) {
mImageManager.smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double *d = (double *) callData;
v->setWindowLevel(d[1], d[0]);
}
}, view, calldata, ImageViewManager::EStudyEBoundsSeries);
}
break;
default:
break;
}
}

View File

@@ -93,7 +93,7 @@ void DicomImageView::initScrollbar() {
mScrollBar->setVisible(true); mScrollBar->setVisible(true);
if (!mIsSlotInited) { if (!mIsSlotInited) {
connect(mScrollBar, &QScrollBar::valueChanged, this, &DicomImageView::scrollBarValueChanged); connect(mScrollBar, &QScrollBar::valueChanged, this, &DicomImageView::scrollBarValueChanged);
connect(this, &DicomImageView::Signal_Transformation, this, &DicomImageView::imageTransformed); connect(this, &DicomImageView::onTransform, this, &DicomImageView::imageTransformed);
mIsSlotInited = true; mIsSlotInited = true;
} }
} }
@@ -193,11 +193,11 @@ void DicomImageView::scrollBarValueChanged(int slice) {
} }
void DicomImageView::viewCleared() { void DicomImageView::viewCleared() {
emit Signal_ViewEmpty(this); emit onViewClear(this);
} }
void DicomImageView::doubleClicked() { void DicomImageView::doubleClicked() {
emit Signal_viewDoubleclicked(this); emit onViewDoubleClick(this);
} }
void DicomImageView::fusionWindowChanged(double level, double width) { void DicomImageView::fusionWindowChanged(double level, double width) {
@@ -214,7 +214,7 @@ void DicomImageView::imageTransformed() {
} }
void DicomImageView::clicked() { void DicomImageView::clicked() {
emit Signal_ViewClicked(this); emit onViewClick(this);
} }
//Widget event---------------------------------------------------------------- //Widget event----------------------------------------------------------------
@@ -246,7 +246,7 @@ void DicomImageView::wheelEvent(QWheelEvent *event) {
void DicomImageView::mousePressEvent(QMouseEvent *event) { void DicomImageView::mousePressEvent(QMouseEvent *event) {
emit Signal_ViewClicked(this); emit onViewClick(this);
} }
void DicomImageView::resizeEvent(QResizeEvent *event) { void DicomImageView::resizeEvent(QResizeEvent *event) {
@@ -285,7 +285,7 @@ void DicomImageView::dropEvent(QDropEvent *e) {
thumbnailImage *tb = qobject_cast<thumbnailImage *>( thumbnailImage *tb = qobject_cast<thumbnailImage *>(
(QObject *) (e->mimeData()->text().toULongLong())); (QObject *) (e->mimeData()->text().toULongLong()));
if (tb) { if (tb) {
emit Signal_DragDropEvent(this, tb); emit onDragDrop(this, tb);
} }
} }
} }
@@ -342,7 +342,7 @@ void DicomImageView::setFusionOpacity(double percent) {
void DicomImageView::unloadFusion() { void DicomImageView::unloadFusion() {
if (hasSeries()) { if (hasSeries()) {
if (isFusion()) { if (isFusion()) {
disconnect(mOverlayView, &DicomImageView::Signal_WindowLevelEventForFusion, disconnect(mOverlayView, &DicomImageView::onFusionWindowChange,
this, &DicomImageView::fusionWindowChanged); this, &DicomImageView::fusionWindowChanged);
this->clearFusionContext(); this->clearFusionContext();
@@ -351,7 +351,7 @@ void DicomImageView::unloadFusion() {
} }
if (IsOverlay()) { if (IsOverlay()) {
disconnect(this, &DicomImageView::Signal_WindowLevelEventForFusion, disconnect(this, &DicomImageView::onFusionWindowChange,
mBaseView, &DicomImageView::fusionWindowChanged); mBaseView, &DicomImageView::fusionWindowChanged);
mBaseView->clearFusionContext(); mBaseView->clearFusionContext();
@@ -371,7 +371,7 @@ void DicomImageView::clearFusionContext() {
//Callbacks------------------------------------------------------------------------------------ //Callbacks------------------------------------------------------------------------------------
void DicomImageView::updateWindowLevelCb() { void DicomImageView::updateWindowLevelCb() {
mImageViewer->UpdateCornerInfo(BOTTOM_RIGHT); mImageViewer->UpdateCornerInfo(BOTTOM_RIGHT);
emit Signal_WindowLevelEventForFusion(mImageViewer->GetColorLevel(), mImageViewer->GetColorWindow()); emit onFusionWindowChange(mImageViewer->GetColorLevel(), mImageViewer->GetColorWindow());
} }
void DicomImageView::scalarEventCb(vtkObject *, unsigned long eventId, void *calldata) { void DicomImageView::scalarEventCb(vtkObject *, unsigned long eventId, void *calldata) {
@@ -393,7 +393,7 @@ void DicomImageView::scalarEventCb(vtkObject *, unsigned long eventId, void *cal
} }
void DicomImageView::doubleclickedEventCb() { void DicomImageView::doubleclickedEventCb() {
emit Signal_viewDoubleclicked(this); emit onViewDoubleClick(this);
} }
//TODO重新匹配该函数部分逻辑可以直接保留需要注意Endxxx系列事件不是仅仅为了sync设计的 //TODO重新匹配该函数部分逻辑可以直接保留需要注意Endxxx系列事件不是仅仅为了sync设计的
@@ -402,21 +402,21 @@ void DicomImageView::syncEventFunc(vtkObject *, unsigned long eid, void *calldat
int *r = (int *) calldata; int *r = (int *) calldata;
switch (eid) { switch (eid) {
case (vtkCommand::EventIds::EndPanEvent): case (vtkCommand::EventIds::EndPanEvent):
this->Signal_SyncEvent(this, VTKIS_IMAGE_PAN, calldata); this->onSync(this, VTKIS_IMAGE_PAN, calldata);
break; break;
case (vtkCommand::EventIds::EndWindowLevelEvent): case (vtkCommand::EventIds::EndWindowLevelEvent):
//update corner info through callback //update corner info through callback
this->Signal_SyncEvent(this, VTKIS_IMAGE_WINDOWLEVEL, calldata); this->onSync(this, VTKIS_IMAGE_WINDOWLEVEL, calldata);
break; break;
case (ActorDraggableInteractorStyle::DraggableStyleEvents::EndDollyEvent): case (ActorDraggableInteractorStyle::DraggableStyleEvents::EndDollyEvent):
this->Signal_SyncEvent(this, VTKIS_IMAGE_ZOOM, calldata); this->onSync(this, VTKIS_IMAGE_ZOOM, calldata);
break; break;
case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): { case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): {
mScrollBar->SetValueSilently(r[0]); mScrollBar->SetValueSilently(r[0]);
//invoke event //invoke event
double focusPoint[3] = {.0, .0, .0}; double focusPoint[3] = {.0, .0, .0};
mImageViewer->GetSlicePoint(focusPoint); mImageViewer->GetSlicePoint(focusPoint);
this->Signal_SyncEvent(this, VTKIS_IMAGE_SLICING, focusPoint); this->onSync(this, VTKIS_IMAGE_SLICING, focusPoint);
break; break;
} }
default: default:
@@ -500,7 +500,7 @@ void DicomImageView::setWindowLevel(double level, double width) {
//You have to call updateConerInfo manually //You have to call updateConerInfo manually
//only mouse event can rely on callback //only mouse event can rely on callback
mImageViewer->UpdateCornerInfo(BOTTOM_RIGHT); mImageViewer->UpdateCornerInfo(BOTTOM_RIGHT);
emit Signal_WindowLevelEventForFusion(level, width); emit onFusionWindowChange(level, width);
} }
} }
@@ -538,7 +538,7 @@ void DicomImageView::hFlipImage() {
mImageViewer->SetSlice(slice); mImageViewer->SetSlice(slice);
mImageViewer->GetRenderWindow()->Render(); mImageViewer->GetRenderWindow()->Render();
emit Signal_Transformation(H_FLIP); emit onTransform(H_FLIP);
} }
} }
@@ -558,7 +558,7 @@ void DicomImageView::vFlipImage() {
mImageViewer->GetRenderer()->ResetCameraClippingRange(); mImageViewer->GetRenderer()->ResetCameraClippingRange();
mImageViewer->SetSlice(slice); mImageViewer->SetSlice(slice);
mImageViewer->GetRenderWindow()->Render(); mImageViewer->GetRenderWindow()->Render();
emit Signal_Transformation(V_FLIP); emit onTransform(V_FLIP);
} }
} }
@@ -572,7 +572,7 @@ void DicomImageView::rotateImage(double angle, TransFormType operation) {
mImageViewer->GetRenderer()->ResetCameraClippingRange(); mImageViewer->GetRenderer()->ResetCameraClippingRange();
mImageViewer->SetSlice(slice); mImageViewer->SetSlice(slice);
// mImageViewer->GetRenderWindow()->Render(); // mImageViewer->GetRenderWindow()->Render();
emit Signal_Transformation(operation); emit onTransform(operation);
} }
} }
@@ -594,7 +594,7 @@ void DicomImageView::ClearTransformations() {
mImageViewer->SetSlice(slice); mImageViewer->SetSlice(slice);
//Render //Render
mImageViewer->GetRenderWindow()->Render(); mImageViewer->GetRenderWindow()->Render();
emit Signal_Transformation(CLEAR); emit onTransform(CLEAR);
} }
} }

View File

@@ -154,7 +154,7 @@ public:
return this->mImageViewer->GetWorldSliceOrientation() == view->mImageViewer->GetWorldSliceOrientation(); return this->mImageViewer->GetWorldSliceOrientation() == view->mImageViewer->GetWorldSliceOrientation();
} }
void SyncSlicePoint(double *point) { void syncSlicePoint(double *point) {
mImageViewer->SyncSlicePoint(point); mImageViewer->SyncSlicePoint(point);
mImageViewer->Render(); mImageViewer->Render();
} }
@@ -163,19 +163,19 @@ public:
signals: signals:
void Signal_ViewEmpty(DicomImageView *view); void onViewClear(DicomImageView *view);
void Signal_ViewClicked(DicomImageView *view); void onViewClick(DicomImageView *view);
void Signal_viewDoubleclicked(DicomImageView *view); void onViewDoubleClick(DicomImageView *view);
void Signal_DragDropEvent(DicomImageView *view, thumbnailImage *tb); void onDragDrop(DicomImageView *view, thumbnailImage *tb);
void Signal_SyncEvent(DicomImageView *view, int interactionMode, void *calldata); void onSync(DicomImageView *view, int interactionMode, void *calldata);
void Signal_WindowLevelEventForFusion(double level, double width); void onFusionWindowChange(double level, double width);
void Signal_Transformation(TransFormType); void onTransform(TransFormType);
public slots: public slots:

View File

@@ -1,214 +1,104 @@
#include "viewcontainerwidget.h" #include "viewcontainerwidget.h"
#include "thumbnailImage.h"
#include "IO/DICOM/DicomLoader.h"
#include <QWidget>
#include <QGridLayout>
#include <QSettings>
#include <QFontDialog> #include <QFontDialog>
#include <QVTKOpenGLNativeWidget.h> #include <QVTKOpenGLNativeWidget.h>
#include "Common/QGlobals.h"
#include <QDebug> #include <QDebug>
#include "qstyleoption.h"
#include "qpainter.h"
#include "cine/pqVCRToolbar.h"
#include <QMessageBox> #include <QMessageBox>
#include <QStyleOption>
#include <QPainter>
#include "Interaction/ActorDraggableInteractorStyle.h" #include "Interaction/ActorDraggableInteractorStyle.h"
#include "Rendering/Measure/MeasureFactory.h" #include "Rendering/Measure/MeasureFactory.h"
//------------------------------------------------------- #include "IO/DICOM/DicomLoader.h"
#include "thumbnailImage.h"
#include "cine/pqVCRToolbar.h"
ViewContainerWidget::ViewContainerWidget(QWidget *parent) : QFrame(parent) {
ViewContainerWidget::ViewContainerWidget(QWidget *parent) :QFrame(parent)
{
QGridLayout *layout = new QGridLayout(this); QGridLayout *layout = new QGridLayout(this);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0); layout->setSpacing(0);
this->setLayout(layout); this->setLayout(layout);
Slot_SetViewLayout(1, 1); viewLayoutChanged(1, 1);
} }
//-------------------------------------------------------
ViewContainerWidget::~ViewContainerWidget() { ViewContainerWidget::~ViewContainerWidget() {
} }
//------------------------------------------------------- void ViewContainerWidget::setInteractionMode(int InteractionMode) {
QList<DicomImageView *>& ViewContainerWidget::getViewList() {
return manager.getViewList();
}
DicomImageView *ViewContainerWidget::getCurrentView() {
return manager.getCurrentView();
}
DicomImageView* ViewContainerWidget::getNextView()
{
bool found = false;
for (int i = 0; i < manager.getViewCount(); ++i)
{
DicomImageView *v = manager.getView(i);
if (found)
{
return v;
}
if (manager.getCurrentView() == v)
{
found = true;
}
}
return nullptr;
}
void ViewContainerWidget::Slot_SyncEvent(DicomImageView *view, int interactionMode, void* calldata)
{
switch (interactionMode)
{
case VTKIS_IMAGE_SLICING:
if (SyncHelper::getSyncItem(SLICE_POS))
{
if (SyncHelper::getSyncState() == AUTO_SYNC)
{
manager.smartDo([](auto v,auto callData){
if (v->hasSeries()) {
double* r = (double*) callData;
v->SyncSlicePoint(r);
v->SyncScrollBar();
}
},view, calldata,ImageViewManager::EStudyEBoundsSeries);
}
if (SyncHelper::getSyncState() == MANUAL_SYNC)
{
manager.smartDo([](auto v,auto callData){
if (v->hasSeries()) {
//disable global trigger slot
int *r = (int *) callData;
v->addSlice(r[1]);
}
},view, calldata,ImageViewManager::EStudyEBoundsSeries);
}
}
break;
case VTKIS_IMAGE_PAN:
if (SyncHelper::getSyncItem(ZOOM_PAN))
{
manager.smartDo([](auto v,auto callData){
if (v->hasSeries()) {
double *d = (double *)callData;
double vector[3] = { d[3] - d[0],d[4] - d[1],d[5] - d[2] };
v->setPanOffset(vector);
}
},view, calldata,ImageViewManager::EStudyEBoundsSeries);
}
break;
case VTKIS_IMAGE_ZOOM:
if (SyncHelper::getSyncItem(ZOOM_PAN))
{
manager.smartDo([](auto v,auto callData){
if (v->hasSeries()) {
double *d = (double *)callData;
v->setZoomScale(d[1]);
}
},view, calldata,ImageViewManager::EStudyEBoundsSeries);
}
break;
case VTKIS_IMAGE_WINDOWLEVEL:
if (SyncHelper::getSyncItem(WIDTH_LEVEL))
{
manager.smartDo([](auto v,auto callData){
if (v->hasSeries()) {
double *d = (double *)callData;
v->setWindowLevel(d[1], d[0]);
}
},view, calldata,ImageViewManager::EStudyEBoundsSeries);
}
break;
default:
break;
}
}
void ViewContainerWidget::SetInteractionMode(int InteractionMode)
{
void *data = (void *) &InteractionMode; void *data = (void *) &InteractionMode;
manager.smartDo([](auto v,auto callData){ mImageManager.smartDo([](auto v, auto callData) {
int *mode = (int *) callData; int *mode = (int *) callData;
if (v->getImageViewer()) if (v->getImageViewer()) {
{
v->getImageViewer()->GetInteractorStyle()->SetInteractionModeFromEnum(*mode); v->getImageViewer()->GetInteractorStyle()->SetInteractionModeFromEnum(*mode);
} }
}, nullptr, data, ImageViewManager::All); }, nullptr, data, ImageViewManager::All);
} }
void ViewContainerWidget::Slot_ViewClicked(DicomImageView *view) { //Current view about-----------------------------------------------------------
DicomImageView *ViewContainerWidget::getCurrentView() {
return mImageManager.getCurrentView();
}
void ViewContainerWidget::setCurrentView(DicomImageView *view) {
//notify before set nullptr
if (mImageManager.getCurrentView()) {
mImageManager.getCurrentView()->setHighlight(false);
}
mImageManager.setCurrentView(view);
if (mImageManager.getCurrentView()) {
mImageManager.getCurrentView()->setHighlight(true);
}
emit onThumbnailTrigger(mImageManager.getCurrentView());
}
void ViewContainerWidget::clearCurrentView() {
viewCleared(mImageManager.getCurrentView());
}
void ViewContainerWidget::viewClicked(DicomImageView *view) {
//set current_view //set current_view
if (manager.getCurrentView() != view) { if (mImageManager.getCurrentView() != view) {
this->setCurrentView(view); this->setCurrentView(view);
} }
} }
void ViewContainerWidget::setCurrentView(DicomImageView *view) { void ViewContainerWidget::viewDoubleClicked(DicomImageView *view) {
//notify before set nullptr
if (manager.getCurrentView()) {
manager.getCurrentView()->setHighlight(false);
}
manager.setCurrentView(view);
if (manager.getCurrentView()) {
manager.getCurrentView()->setHighlight(true);
}
emit Signal_NotifyThumbnail(manager.getCurrentView());
}
//-------------------------------------------------------
/**
* @brief ViewContainerWidget::Slot_ViewDoubleClicked
* 双击 view(放大缩小)
* @param view
*/
void ViewContainerWidget::Slot_ViewDoubleClicked(DicomImageView *view) {
if (!view) { if (!view) {
return; return;
} }
if (maxed_) { if (mMaxed) {
manager.smartDo([](auto v,auto callData){v->setVisible(true);}, nullptr,nullptr, ImageViewManager::All); mImageManager.smartDo([](auto v, auto callData) { v->setVisible(true); }, nullptr, nullptr,
maxed_ = false; ImageViewManager::All);
} mMaxed = false;
else { } else {
manager.smartDo([](auto v,auto callData){v->setVisible(false);},nullptr,nullptr, ImageViewManager::AllExceptSelf); mImageManager.smartDo([](auto v, auto callData) { v->setVisible(false); }, nullptr, nullptr,
ImageViewManager::AllExceptSelf);
view->setVisible(true); view->setVisible(true);
maxed_ = true; mMaxed = true;
} }
} }
//------------------------------------------------------- void ViewContainerWidget::viewLayoutChanged(int col, int row) {
/**
* @brief ViewContainerWidget::Slot_SetViewLayout
* @param col
* @param row
*/
void ViewContainerWidget::Slot_SetViewLayout(int col, int row) {
if (!(col > 0 && row > 0)) { if (!(col > 0 && row > 0)) {
return; return;
} }
for (int i = 0; i < manager.getViewCount(); i++) { for (int i = 0; i < mImageManager.getViewCount(); i++) {
DicomImageView *v = manager.getView(i); DicomImageView *v = mImageManager.getView(i);
this->layout()->removeWidget(v); this->layout()->removeWidget(v);
} }
int viewCount = col * row; int viewCount = col * row;
while (viewCount < manager.getViewCount()) { while (viewCount < mImageManager.getViewCount()) {
DicomImageView *v = manager.getView(manager.getViewCount()-1); DicomImageView *v = mImageManager.getView(mImageManager.getViewCount() - 1);
//YTC:better compare before delete //YTC:better compare before delete
if (manager.getCurrentView() == v) if (mImageManager.getCurrentView() == v) {
{ mImageManager.setCurrentView(mImageManager.getView(0));
manager.setCurrentView(manager.getView(0));
} }
manager.remove(v); mImageManager.remove(v);
} }
// //
DicomImageView *view; DicomImageView *view;
@@ -222,16 +112,13 @@ void ViewContainerWidget::Slot_SetViewLayout(int col, int row) {
for (int i = 0; i < row; ++i) { for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) { for (int j = 0; j < col; ++j) {
if (i * col + j < manager.getViewCount()) { if (i * col + j < mImageManager.getViewCount()) {
view = manager.getView(i * col + j); view = mImageManager.getView(i * col + j);
} } else {
else { view = addNewView();
view = createImageView(this);
manager.add(view);
} }
if (view->IsCine()) if (view->IsCine()) {
{
//delay //delay
pqVCRToolbar *vcr_tool = view->getVCRToolbar(); pqVCRToolbar *vcr_tool = view->getVCRToolbar();
int n_x = tl_x + (j + 0.5) * grid_x - VCRHelper::vcr_toolbar_offset; int n_x = tl_x + (j + 0.5) * grid_x - VCRHelper::vcr_toolbar_offset;
@@ -245,152 +132,123 @@ void ViewContainerWidget::Slot_SetViewLayout(int col, int row) {
} }
} }
if ((!manager.getCurrentView()) && (manager.getViewCount()>0)) { if ((!mImageManager.getCurrentView()) && (mImageManager.getViewCount() > 0)) {
Slot_ViewClicked(manager.getView(0)); viewClicked(mImageManager.getView(0));
} }
} }
//------------------------------------------------------- void ViewContainerWidget::viewCleared(DicomImageView *view) {
DicomImageView *ViewContainerWidget::createImageView(QWidget* parent) { if (view != nullptr) {
DicomImageView *v = new DicomImageView(parent);
connect(v, &DicomImageView::Signal_ViewEmpty,
this, &ViewContainerWidget::Slot_ViewEmpty);
connect(v, &DicomImageView::Signal_ViewClicked,
this, &ViewContainerWidget::Slot_ViewClicked);
connect(v, &DicomImageView::Signal_viewDoubleclicked,
this, &ViewContainerWidget::Slot_ViewDoubleClicked);
connect(v, &DicomImageView::Signal_DragDropEvent,
this, &ViewContainerWidget::Slot_DragDropEvent);
connect(v, &DicomImageView::Signal_SyncEvent,
this, &ViewContainerWidget::Slot_SyncEvent);
return v;
}
void ViewContainerWidget::resizeEvent(QResizeEvent *e) {
QWidget::resizeEvent(e);
}
void ViewContainerWidget::emptyCurrentView()
{
Slot_ViewEmpty(manager.getCurrentView());
}
void ViewContainerWidget::Slot_ViewEmpty(DicomImageView *view)
{
if (view != nullptr)
{
view->resetView(); view->resetView();
} }
} }
void ViewContainerWidget::Slot_DragDropEvent(DicomImageView *view, thumbnailImage* tb) void ViewContainerWidget::dragDropped(DicomImageView *view, thumbnailImage *tb) {
{
auto serie_info = tb->getSeriesInfo(); auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view);
setCurrentView(view); setCurrentView(view);
viewReload(serie_info->GetUniqueID());
} }
void ViewContainerWidget::Slot_ThumbnailClickEvent(thumbnailImage* tb) void ViewContainerWidget::thumbnailClicked(thumbnailImage *tb) {
{
DicomImageView *view = manager.getCurrentView();
if (nullptr == view)
{
return;
}
auto serie_info = tb->getSeriesInfo(); auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view); viewReload(serie_info->GetUniqueID());
manager.setCurrentView(view);
} }
void ViewContainerWidget::resetToOneView() { void ViewContainerWidget::viewReload(const std::string &unique_info) {
Slot_SetViewLayout(1,1); if (!mImageManager.getCurrentView()) return;
while(manager.getViewCount()>1){ mImageManager.getCurrentView()->unloadFusion();
manager.remove(1);
}
DicomImageView* v = manager.getView(0);
manager.clear();
manager.add(v);
manager.setCurrentView(v);
}
void ViewContainerWidget::replaceViewWithSerie(const std::string& uniqueid, DicomImageView* curV)
{
if (!curV)
{
curV= manager.getCurrentView();
}
curV->unloadFusion();
DicomLoader *helper = DicomLoader::GetInstance(); DicomLoader *helper = DicomLoader::GetInstance();
curV->loadSeries(helper->getSeriesImageSet(uniqueid)); mImageManager.getCurrentView()->loadSeries(helper->getSeriesImageSet(unique_info));
curV->render(); mImageManager.getCurrentView()->render();
} }
void ViewContainerWidget::toggleViewWithFusion() //view layout about------------------------------------------------------------
{ DicomImageView *ViewContainerWidget::addNewView() {
if (manager.getCurrentView()) DicomImageView *v = new DicomImageView(this);
{
if (manager.getCurrentView()->hasSeries() && manager.getCurrentView()->isFusion()) connect(v, &DicomImageView::onViewClear,
{ this, &ViewContainerWidget::viewCleared);
removeCurrentViewWithFusion();
connect(v, &DicomImageView::onViewClick,
this, &ViewContainerWidget::viewClicked);
connect(v, &DicomImageView::onViewDoubleClick,
this, &ViewContainerWidget::viewDoubleClicked);
connect(v, &DicomImageView::onDragDrop,
this, &ViewContainerWidget::dragDropped);
connect(v, &DicomImageView::onSync,
this, &ViewContainerWidget::viewSynced);
mImageManager.add(v);
return v;
}
void ViewContainerWidget::resetLayoutToSingle() {
viewLayoutChanged(1, 1);
while (mImageManager.getViewCount() > 1) {
mImageManager.remove(1);
}
DicomImageView *v = mImageManager.getView(0);
mImageManager.clear();
mImageManager.add(v);
mImageManager.setCurrentView(v);
}
//fusion about-----------------------------------------------------------------
void ViewContainerWidget::switchFusion() {
if (mImageManager.getCurrentView()) {
if (mImageManager.getCurrentView()->hasSeries() && mImageManager.getCurrentView()->isFusion()) {
unloadFusion();
} else {
loadFusion();
} }
else
{
replaceViewWithFusion();
} }
} }
} void ViewContainerWidget::loadFusion() {
for (int i = 0; i < mImageManager.getViewCount(); ++i) {
if (mImageManager.getView(i) == mImageManager.getCurrentView()) continue;
DicomImageView *overlap_view = mImageManager.getView(i);
if (checkFusion(mImageManager.getCurrentView(), overlap_view)) {
connect(overlap_view, &DicomImageView::onFusionWindowChange,
mImageManager.getCurrentView(), &DicomImageView::fusionWindowChanged);
void ViewContainerWidget::replaceViewWithFusion() mImageManager.getCurrentView()->setFusionInput(overlap_view);
{ mImageManager.getCurrentView()->render();
for (int i = 0; i < manager.getViewCount(); ++i) {
if (manager.getView(i) == manager.getCurrentView()) continue;
DicomImageView * overlap_view = manager.getView(i);
if (checkFusionStatus(manager.getCurrentView(), overlap_view))
{
connect(overlap_view, &DicomImageView::Signal_WindowLevelEventForFusion,
manager.getCurrentView(), &DicomImageView::fusionWindowChanged);
manager.getCurrentView()->setFusionInput(overlap_view);
manager.getCurrentView()->render();
return; return;
} }
} }
QMessageBox::information(this, "Warning", "Invalid Fusion!"); QMessageBox::information(this, "Warning", "Invalid Fusion!");
} }
void ViewContainerWidget::removeCurrentViewWithFusion()
{ void ViewContainerWidget::unloadFusion() {
if (manager.getCurrentView()) { if (mImageManager.getCurrentView()) {
manager.getCurrentView()->unloadFusion(); mImageManager.getCurrentView()->unloadFusion();
} }
} }
bool ViewContainerWidget::checkFusionStatus(DicomImageView *base, DicomImageView* overlap) bool ViewContainerWidget::checkFusion(DicomImageView *base, DicomImageView *overlap) {
{
SeriesImageSet *baseSeries = base->getSeriesInstance(); SeriesImageSet *baseSeries = base->getSeriesInstance();
SeriesImageSet *overlapSeries = overlap->getSeriesInstance(); SeriesImageSet *overlapSeries = overlap->getSeriesInstance();
// no data // no data
if (!base->hasSeries() || !overlap->hasSeries()) return false; if (!base->hasSeries() || !overlap->hasSeries()) return false;
// diff study // diff study
if (baseSeries->getStudyUID() == nullptr || if (baseSeries->getStudyUID() == nullptr ||
strcmp(baseSeries->getStudyUID(), overlapSeries->getStudyUID())!=0) return false; strcmp(baseSeries->getStudyUID(), overlapSeries->getStudyUID()) != 0)
return false;
//same series //same series
if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false; if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false;
return baseSeries->IntersectWorldBounds(overlapSeries); return baseSeries->IntersectWorldBounds(overlapSeries);
} }
//Corner about-----------------------------------------------------------------
void ViewContainerWidget::updateCornerInfoAll() { void ViewContainerWidget::updateCornerInfoAll() {
manager.smartDo([](auto v, auto calldata) { mImageManager.smartDo([](auto v, auto calldata) {
if (v->hasSeries()) { if (v->hasSeries()) {
v->updateCornerInfoAll(); v->updateCornerInfoAll();
} }
@@ -398,7 +256,7 @@ void ViewContainerWidget::updateCornerInfoAll() {
} }
void ViewContainerWidget::updateCornerInfoPrivacy() { void ViewContainerWidget::updateCornerInfoPrivacy() {
manager.smartDo([](auto v, auto calldata) { mImageManager.smartDo([](auto v, auto calldata) {
if (v->hasSeries()) { if (v->hasSeries()) {
v->updateCornerInfoPrivacy(); v->updateCornerInfoPrivacy();
} }
@@ -406,16 +264,20 @@ void ViewContainerWidget::updateCornerInfoPrivacy() {
} }
void ViewContainerWidget::render() { void ViewContainerWidget::render() {
manager.smartDo([](auto v, auto calldata) { mImageManager.smartDo([](auto v, auto) {
if (v->hasSeries()) { if (v->hasSeries()) {
v->render(); v->render();
} }
}, nullptr, nullptr, ImageViewManager::All); }, nullptr, nullptr, ImageViewManager::All);
} }
void ViewContainerWidget::resizeEvent(QResizeEvent *e) {
QWidget::resizeEvent(e);
}
void ViewContainerWidget::activeMeasure() { void ViewContainerWidget::activeMeasure() {
manager.smartDo([](auto v, auto calldata) { mImageManager.smartDo([](auto v, auto) {
if (v->hasSeries()) { if (v->hasSeries()) {
Measure *measure = MeasureFactory::getMeasure((AnnotationActorType) MeasureHelper::getMeasureType()); Measure *measure = MeasureFactory::getMeasure((AnnotationActorType) MeasureHelper::getMeasureType());
v->activeMeasure(measure); v->activeMeasure(measure);
@@ -423,11 +285,13 @@ void ViewContainerWidget::activeMeasure() {
}, nullptr, nullptr, ImageViewManager::All); }, nullptr, nullptr, ImageViewManager::All);
} }
void ViewContainerWidget::SetCurrentViewSliceOrientation(int type) { void ViewContainerWidget::setCurrentViewSliceOrientation(int orientation) {
manager.getCurrentView()->getSliceOrientation(type); mImageManager.getCurrentView()->getSliceOrientation(orientation);
} }
int ViewContainerWidget::GetCurrentViewSliceOrientation() { int ViewContainerWidget::getCurrentViewSliceOrientation() {
return manager.getCurrentView()->getSliceOrientation();; return mImageManager.getCurrentView()->getSliceOrientation();;
} }

View File

@@ -1,4 +1,5 @@
#pragma once #ifndef OMEGAV_VIEW_CONTAINER_WIDGET_H
#define OMEGAV_VIEW_CONTAINER_WIDGET_H
#include <QFrame> #include <QFrame>
#include <QScrollBar> #include <QScrollBar>
#include "Common/QGlobals.h" #include "Common/QGlobals.h"
@@ -6,8 +7,11 @@
#include "UI/Manager/ImageViewManager.h" #include "UI/Manager/ImageViewManager.h"
class QGridLayout; class QGridLayout;
class DicomImageView; class DicomImageView;
class SeriesImageSet; class SeriesImageSet;
class Measure; class Measure;
class ViewContainerWidget : public QFrame { class ViewContainerWidget : public QFrame {
@@ -16,59 +20,80 @@ class ViewContainerWidget : public QFrame {
public: public:
explicit ViewContainerWidget(QWidget *parent = nullptr); explicit ViewContainerWidget(QWidget *parent = nullptr);
~ViewContainerWidget(); ~ViewContainerWidget();
DicomImageView *getCurrentView(); DicomImageView *getCurrentView();
DicomImageView* getNextView();
QList<DicomImageView*>& getViewList() ;
void setCurrentView(DicomImageView *view); void setCurrentView(DicomImageView *view);
void emptyCurrentView();
void clearCurrentView();
void updateCornerInfoAll(); void updateCornerInfoAll();
void updateCornerInfoPrivacy(); void updateCornerInfoPrivacy();
void activeMeasure(); void activeMeasure();
void render(); void render();
void replaceViewWithSerie(const std::string& unique_info, void viewReload(const std::string &unique_info);
DicomImageView* curV = nullptr);
void resetToOneView(); void resetLayoutToSingle();
//fusion //fusion-------------------------------------------------------------------
void toggleViewWithFusion(); void switchFusion();
void removeCurrentViewWithFusion();
void SetInteractionMode(int InteractionMode);
void SetCurrentViewSliceOrientation(int orientation); void loadFusion();
int GetCurrentViewSliceOrientation();
void unloadFusion();
void setInteractionMode(int InteractionMode);
void setCurrentViewSliceOrientation(int orientation);
int getCurrentViewSliceOrientation();
signals: signals:
void Signal_NotifyThumbnail(DicomImageView *view);
void onThumbnailTrigger(DicomImageView *view);
public slots: public slots:
void Slot_ViewEmpty(DicomImageView *view);
void Slot_SetViewLayout(int col, int row); void viewCleared(DicomImageView *view);
void Slot_ViewClicked(DicomImageView *view);
void Slot_ViewDoubleClicked(DicomImageView *view); /**
void Slot_DragDropEvent(DicomImageView *view, thumbnailImage* tb); * @brief ViewContainerWidget::viewLayoutChanged
* @param col
* @param row
*/
void viewLayoutChanged(int col, int row);
void viewClicked(DicomImageView *view);
/**
* @brief ViewContainerWidget::viewDoubleClicked
* 双击 view(放大缩小)
* @param view
*/
void viewDoubleClicked(DicomImageView *view);
void dragDropped(DicomImageView *view, thumbnailImage *tb);
/** /**
* 缩略图点击槽函数会导致当前选中的view重新load数据 * 缩略图点击槽函数会导致当前选中的view重新load数据
* @param tb 缩略图对象 * @param tb 缩略图对象
* @return * @return
*/ */
void Slot_ThumbnailClickEvent(thumbnailImage* tb); void thumbnailClicked(thumbnailImage *tb);
void Slot_SyncEvent(DicomImageView *view, int interactionMode, void* calldata);
void viewSynced(DicomImageView *view, int interactionMode, void *calldata);
protected: protected:
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
private: private:
//fusion
void replaceViewWithFusion();
/** /**
* 判断是否能fusion,判断依据为是否相同Study * 判断是否能fusion,判断依据为是否相同Study
@@ -78,11 +103,11 @@ private:
* @param overlap 覆盖数据源View * @param overlap 覆盖数据源View
* @return * @return
*/ */
bool checkFusionStatus(DicomImageView *base, DicomImageView* overlap); bool checkFusion(DicomImageView *base, DicomImageView *overlap);
DicomImageView *createImageView(QWidget* parent); DicomImageView *addNewView();
QList<DicomImageView*> view_list_;
DicomImageView *current_view_ = nullptr; ImageViewManager mImageManager;
ImageViewManager manager; bool mMaxed = false;
bool maxed_ = false;
}; };
#endif

View File

@@ -205,7 +205,7 @@ void QDicomViewer::createToolButton()
this->SetupCloseTool(btnclose); this->SetupCloseTool(btnclose);
connect(btnMPR,&QToolButton::clicked,[=](){ connect(btnMPR,&QToolButton::clicked,[=](){
ui->viewContainer->SetCurrentViewSliceOrientation((ui->viewContainer->GetCurrentViewSliceOrientation()+1)%3); ui->viewContainer->setCurrentViewSliceOrientation((ui->viewContainer->getCurrentViewSliceOrientation() + 1) % 3);
}); });
} }
@@ -494,14 +494,14 @@ void QDicomViewer::SetupFusionTool(QToolButton* fusionBtn)
fusionBtn->setToolTip(QString("Fusion")); fusionBtn->setToolTip(QString("Fusion"));
connect(fusionBtn, &QToolButton::clicked, this, [&] { connect(fusionBtn, &QToolButton::clicked, this, [&] {
ui->viewContainer->toggleViewWithFusion(); ui->viewContainer->switchFusion();
}); });
QMenu* m; QMenu* m;
m = new QMenu(this); m = new QMenu(this);
m->addAction(tr("Reset Fusion"), this, [&] { m->addAction(tr("Reset Fusion"), this, [&] {
ui->viewContainer->removeCurrentViewWithFusion(); ui->viewContainer->unloadFusion();
}); });
fusionBtn->setPopupMode(QToolButton::MenuButtonPopup); fusionBtn->setPopupMode(QToolButton::MenuButtonPopup);
fusionBtn->setMenu(m); fusionBtn->setMenu(m);
@@ -512,7 +512,7 @@ void QDicomViewer::SetupSliceTool(QToolButton* sliceBtn)
sliceBtn->setToolTip(QString("Browse series")); sliceBtn->setToolTip(QString("Browse series"));
connect(sliceBtn, &QToolButton::clicked, this, [&] { connect(sliceBtn, &QToolButton::clicked, this, [&] {
//ui->viewContainer->setLeftButtonState(VTKIS_SLICE); //ui->viewContainer->setLeftButtonState(VTKIS_SLICE);
ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_SLICING); ui->viewContainer->setInteractionMode(VTKIS_IMAGE_SLICING);
}); });
} }
//视窗操作pan //视窗操作pan
@@ -521,7 +521,7 @@ void QDicomViewer::SetupPanTool(QToolButton* panBtn)
panBtn->setToolTip(QString("Pan image")); panBtn->setToolTip(QString("Pan image"));
connect(panBtn, &QToolButton::clicked, this, [&] { connect(panBtn, &QToolButton::clicked, this, [&] {
//ui->viewContainer->setLeftButtonState(VTKIS_PAN); //ui->viewContainer->setLeftButtonState(VTKIS_PAN);
ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_PAN); ui->viewContainer->setInteractionMode(VTKIS_IMAGE_PAN);
}); });
} }
//视窗操作zoom //视窗操作zoom
@@ -530,7 +530,7 @@ void QDicomViewer::SetupZoomTool(QToolButton* zoomBtn)
zoomBtn->setToolTip(QString("Zoom image")); zoomBtn->setToolTip(QString("Zoom image"));
connect(zoomBtn, &QToolButton::clicked, this, [&] { connect(zoomBtn, &QToolButton::clicked, this, [&] {
//ui->viewContainer->setLeftButtonState(VTKIS_DOLLY); //ui->viewContainer->setLeftButtonState(VTKIS_DOLLY);
ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_ZOOM); ui->viewContainer->setInteractionMode(VTKIS_IMAGE_ZOOM);
}); });
} }
@@ -540,7 +540,7 @@ void QDicomViewer::SetupAdjustTool(QToolButton* winlevelBtn)
winlevelBtn->setToolTip(QString("Adjust window level")); winlevelBtn->setToolTip(QString("Adjust window level"));
connect(winlevelBtn, &QToolButton::clicked, this, [&] { connect(winlevelBtn, &QToolButton::clicked, this, [&] {
//ui->viewContainer->setLeftButtonState(VTKIS_WINDOW_LEVEL); //ui->viewContainer->setLeftButtonState(VTKIS_WINDOW_LEVEL);
ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_WINDOWLEVEL); ui->viewContainer->setInteractionMode(VTKIS_IMAGE_WINDOWLEVEL);
}); });
// Menu // Menu
@@ -579,7 +579,7 @@ void QDicomViewer::SetupEmptyTool(QToolButton* emptyBtn)
{ {
emptyBtn->setToolTip(QString("Delete current series")); emptyBtn->setToolTip(QString("Delete current series"));
connect(emptyBtn, &QToolButton::clicked, this, [&] { connect(emptyBtn, &QToolButton::clicked, this, [&] {
ui->viewContainer->emptyCurrentView(); ui->viewContainer->clearCurrentView();
}); });
} }
@@ -843,7 +843,7 @@ void QDicomViewer::SetupGridTool(QToolButton* gridBtn) {
//qDebug() << &gridBtn; //qDebug() << &gridBtn;
GridPopWidget* gpw = new GridPopWidget(gridBtn); GridPopWidget* gpw = new GridPopWidget(gridBtn);
connect(gpw, &GridPopWidget::Signal_ViewLayout, connect(gpw, &GridPopWidget::Signal_ViewLayout,
ui->viewContainer, &ViewContainerWidget::Slot_SetViewLayout); ui->viewContainer, &ViewContainerWidget::viewLayoutChanged);
gpw->move(this->geometry().topLeft() + gridBtn->geometry().bottomLeft() + QPoint(25, 25)); gpw->move(this->geometry().topLeft() + gridBtn->geometry().bottomLeft() + QPoint(25, 25));
gpw->show(); gpw->show();
}); });
@@ -852,19 +852,19 @@ void QDicomViewer::SetupGridTool(QToolButton* gridBtn) {
void QDicomViewer::SetupConnections() void QDicomViewer::SetupConnections()
{ {
//通知左侧的缩略图bar 当前选中series的变换 //通知左侧的缩略图bar 当前选中series的变换
connect(ui->viewContainer, &ViewContainerWidget::Signal_NotifyThumbnail, connect(ui->viewContainer, &ViewContainerWidget::onThumbnailTrigger,
ui->thumbnailBar, &ThumbnailBarWidget::Slot_setCurrentThumbnail); ui->thumbnailBar, &ThumbnailBarWidget::Slot_setCurrentThumbnail);
//通知右侧显示区域当前有series被点击 //通知右侧显示区域当前有series被点击
connect(ui->thumbnailBar, &ThumbnailBarWidget::Signal_ThumbClicked, connect(ui->thumbnailBar, &ThumbnailBarWidget::Signal_ThumbClicked,
ui->viewContainer, &ViewContainerWidget::Slot_ThumbnailClickEvent); ui->viewContainer, &ViewContainerWidget::thumbnailClicked);
connect(ui->toolBar,&QToolBar::visibilityChanged, connect(ui->toolBar,&QToolBar::visibilityChanged,
this, &QDicomViewer::Slot_ToolbarVisibilityChanged); this, &QDicomViewer::Slot_ToolbarVisibilityChanged);
//connect(ui->viewContainer, SIGNAL(Signal_NotifyThumbnail(DicomImageView*)), //connect(ui->viewContainer, SIGNAL(onThumbnailTrigger(DicomImageView*)),
// ui->vcr_toolbar, SLOT(setImageView(DicomImageView*))); // ui->vcr_toolbar, SLOT(setImageView(DicomImageView*)));
//connect(ui->thumbnailBar, SIGNAL(Signal_CopyDicomView(SeriesInfo_t*)), //connect(ui->thumbnailBar, SIGNAL(Signal_CopyDicomView(SeriesInfo_t*)),
@@ -896,14 +896,14 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
displayThumbnailBar(true); displayThumbnailBar(true);
//必须首先重置成1个窗口的布局 //必须首先重置成1个窗口的布局
ui->viewContainer->resetToOneView(); ui->viewContainer->resetLayoutToSingle();
DicomLoader *helper = DicomLoader::GetInstance(); DicomLoader *helper = DicomLoader::GetInstance();
helper->reset(); helper->reset();
//load image and tag //load image and tag
helper->readTags(dicomName, openMode); helper->readTags(dicomName, openMode);
auto unique = helper->getDefaultUniqueID(); auto unique = helper->getDefaultUniqueID();
ui->viewContainer->replaceViewWithSerie(unique); ui->viewContainer->viewReload(unique);
//view clicked will notify thumbnailbar update //view clicked will notify thumbnailbar update
ui->thumbnailBar->updateThumbnailBar(); ui->thumbnailBar->updateThumbnailBar();