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,433 +1,297 @@
#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);
{ layout->setContentsMargins(0, 0, 0, 0);
QGridLayout * layout = new QGridLayout(this); layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0); this->setLayout(layout);
layout->setSpacing(0); viewLayoutChanged(1, 1);
this->setLayout(layout);
Slot_SetViewLayout(1, 1);
} }
//-------------------------------------------------------
ViewContainerWidget::~ViewContainerWidget() { ViewContainerWidget::~ViewContainerWidget() {
} }
//------------------------------------------------------- void ViewContainerWidget::setInteractionMode(int InteractionMode) {
QList<DicomImageView *>& ViewContainerWidget::getViewList() { void *data = (void *) &InteractionMode;
return manager.getViewList(); mImageManager.smartDo([](auto v, auto callData) {
} int *mode = (int *) callData;
if (v->getImageViewer()) {
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;
manager.smartDo([](auto v,auto callData){
int* mode = (int *)callData;
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-----------------------------------------------------------
//set current_view DicomImageView *ViewContainerWidget::getCurrentView() {
if (manager.getCurrentView() != view) { return mImageManager.getCurrentView();
this->setCurrentView(view);
}
} }
void ViewContainerWidget::setCurrentView(DicomImageView *view) { void ViewContainerWidget::setCurrentView(DicomImageView *view) {
//notify before set nullptr //notify before set nullptr
if (manager.getCurrentView()) { if (mImageManager.getCurrentView()) {
manager.getCurrentView()->setHighlight(false); mImageManager.getCurrentView()->setHighlight(false);
} }
manager.setCurrentView(view); mImageManager.setCurrentView(view);
if (manager.getCurrentView()) { if (mImageManager.getCurrentView()) {
manager.getCurrentView()->setHighlight(true); mImageManager.getCurrentView()->setHighlight(true);
} }
emit Signal_NotifyThumbnail(manager.getCurrentView()); emit onThumbnailTrigger(mImageManager.getCurrentView());
} }
//------------------------------------------------------- void ViewContainerWidget::clearCurrentView() {
/** viewCleared(mImageManager.getCurrentView());
* @brief ViewContainerWidget::Slot_ViewDoubleClicked
* 双击 view(放大缩小)
* @param view
*/
void ViewContainerWidget::Slot_ViewDoubleClicked(DicomImageView *view) {
if (!view) {
return;
}
if (maxed_) {
manager.smartDo([](auto v,auto callData){v->setVisible(true);}, nullptr,nullptr, ImageViewManager::All);
maxed_ = false;
}
else {
manager.smartDo([](auto v,auto callData){v->setVisible(false);},nullptr,nullptr, ImageViewManager::AllExceptSelf);
view->setVisible(true);
maxed_ = true;
}
} }
//------------------------------------------------------- void ViewContainerWidget::viewClicked(DicomImageView *view) {
/** //set current_view
* @brief ViewContainerWidget::Slot_SetViewLayout if (mImageManager.getCurrentView() != view) {
* @param col this->setCurrentView(view);
* @param row }
*/
void ViewContainerWidget::Slot_SetViewLayout(int col, int row) {
if (!(col > 0 && row > 0)) {
return;
}
for (int i = 0; i < manager.getViewCount(); i++) {
DicomImageView *v = manager.getView(i);
this->layout()->removeWidget(v);
}
int viewCount = col * row;
while (viewCount < manager.getViewCount()) {
DicomImageView *v = manager.getView(manager.getViewCount()-1);
//YTC:better compare before delete
if (manager.getCurrentView() == v)
{
manager.setCurrentView(manager.getView(0));
}
manager.remove(v);
}
//
DicomImageView *view;
int tl_x = this->geometry().topLeft().x();
int tl_y = this->geometry().topLeft().y();
int br_x = this->geometry().bottomRight().x();
int br_y = this->geometry().bottomRight().y();
int grid_x = (br_x - tl_x) / col;
int grid_y = (br_y - tl_y) / row;
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (i * col + j < manager.getViewCount()) {
view = manager.getView(i * col + j);
}
else {
view = createImageView(this);
manager.add(view);
}
if (view->IsCine())
{
//delay
pqVCRToolbar* vcr_tool = view->getVCRToolbar();
int n_x = tl_x + (j + 0.5) * grid_x - VCRHelper::vcr_toolbar_offset;
int n_y = tl_y + (i + 1)*grid_y;
vcr_tool->move(n_x, n_y);
}
view->getGLWidget()->show();
QGridLayout *layout = qobject_cast<QGridLayout*>(this->layout());
layout->addWidget(view, i, j);
}
}
if ((!manager.getCurrentView()) && (manager.getViewCount()>0)) {
Slot_ViewClicked(manager.getView(0));
}
} }
//------------------------------------------------------- void ViewContainerWidget::viewDoubleClicked(DicomImageView *view) {
DicomImageView *ViewContainerWidget::createImageView(QWidget* parent) { if (!view) {
DicomImageView *v = new DicomImageView(parent); return;
}
connect(v, &DicomImageView::Signal_ViewEmpty, if (mMaxed) {
this, &ViewContainerWidget::Slot_ViewEmpty); mImageManager.smartDo([](auto v, auto callData) { v->setVisible(true); }, nullptr, nullptr,
ImageViewManager::All);
connect(v, &DicomImageView::Signal_ViewClicked, mMaxed = false;
this, &ViewContainerWidget::Slot_ViewClicked); } else {
mImageManager.smartDo([](auto v, auto callData) { v->setVisible(false); }, nullptr, nullptr,
connect(v, &DicomImageView::Signal_viewDoubleclicked, ImageViewManager::AllExceptSelf);
this, &ViewContainerWidget::Slot_ViewDoubleClicked); view->setVisible(true);
mMaxed = true;
}
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) { void ViewContainerWidget::viewLayoutChanged(int col, int row) {
QWidget::resizeEvent(e);
if (!(col > 0 && row > 0)) {
return;
}
for (int i = 0; i < mImageManager.getViewCount(); i++) {
DicomImageView *v = mImageManager.getView(i);
this->layout()->removeWidget(v);
}
int viewCount = col * row;
while (viewCount < mImageManager.getViewCount()) {
DicomImageView *v = mImageManager.getView(mImageManager.getViewCount() - 1);
//YTC:better compare before delete
if (mImageManager.getCurrentView() == v) {
mImageManager.setCurrentView(mImageManager.getView(0));
}
mImageManager.remove(v);
}
//
DicomImageView *view;
int tl_x = this->geometry().topLeft().x();
int tl_y = this->geometry().topLeft().y();
int br_x = this->geometry().bottomRight().x();
int br_y = this->geometry().bottomRight().y();
int grid_x = (br_x - tl_x) / col;
int grid_y = (br_y - tl_y) / row;
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (i * col + j < mImageManager.getViewCount()) {
view = mImageManager.getView(i * col + j);
} else {
view = addNewView();
}
if (view->IsCine()) {
//delay
pqVCRToolbar *vcr_tool = view->getVCRToolbar();
int n_x = tl_x + (j + 0.5) * grid_x - VCRHelper::vcr_toolbar_offset;
int n_y = tl_y + (i + 1) * grid_y;
vcr_tool->move(n_x, n_y);
}
view->getGLWidget()->show();
QGridLayout *layout = qobject_cast<QGridLayout *>(this->layout());
layout->addWidget(view, i, j);
}
}
if ((!mImageManager.getCurrentView()) && (mImageManager.getViewCount() > 0)) {
viewClicked(mImageManager.getView(0));
}
} }
void ViewContainerWidget::emptyCurrentView() void ViewContainerWidget::viewCleared(DicomImageView *view) {
{ if (view != nullptr) {
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)
{
auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view);
setCurrentView(view);
}
void ViewContainerWidget::Slot_ThumbnailClickEvent(thumbnailImage* tb)
{
DicomImageView *view = manager.getCurrentView();
if (nullptr == view)
{
return;
}
auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view);
manager.setCurrentView(view);
}
void ViewContainerWidget::resetToOneView() {
Slot_SetViewLayout(1,1);
while(manager.getViewCount()>1){
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) void ViewContainerWidget::dragDropped(DicomImageView *view, thumbnailImage *tb) {
{ auto serie_info = tb->getSeriesInfo();
if (!curV) setCurrentView(view);
{ viewReload(serie_info->GetUniqueID());
curV= manager.getCurrentView();
}
void ViewContainerWidget::thumbnailClicked(thumbnailImage *tb) {
auto serie_info = tb->getSeriesInfo();
viewReload(serie_info->GetUniqueID());
}
void ViewContainerWidget::viewReload(const std::string &unique_info) {
if (!mImageManager.getCurrentView()) return;
mImageManager.getCurrentView()->unloadFusion();
DicomLoader *helper = DicomLoader::GetInstance();
mImageManager.getCurrentView()->loadSeries(helper->getSeriesImageSet(unique_info));
mImageManager.getCurrentView()->render();
}
//view layout about------------------------------------------------------------
DicomImageView *ViewContainerWidget::addNewView() {
DicomImageView *v = new DicomImageView(this);
connect(v, &DicomImageView::onViewClear,
this, &ViewContainerWidget::viewCleared);
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);
} }
curV->unloadFusion(); DicomImageView *v = mImageManager.getView(0);
DicomLoader *helper = DicomLoader::GetInstance(); mImageManager.clear();
curV->loadSeries(helper->getSeriesImageSet(uniqueid)); mImageManager.add(v);
curV->render(); mImageManager.setCurrentView(v);
} }
void ViewContainerWidget::toggleViewWithFusion() //fusion about-----------------------------------------------------------------
{ void ViewContainerWidget::switchFusion() {
if (manager.getCurrentView()) if (mImageManager.getCurrentView()) {
{
if (manager.getCurrentView()->hasSeries() && manager.getCurrentView()->isFusion())
{
removeCurrentViewWithFusion();
}
else
{
replaceViewWithFusion();
}
}
if (mImageManager.getCurrentView()->hasSeries() && mImageManager.getCurrentView()->isFusion()) {
unloadFusion();
} else {
loadFusion();
}
}
} }
void ViewContainerWidget::replaceViewWithFusion() void ViewContainerWidget::loadFusion() {
{ for (int i = 0; i < mImageManager.getViewCount(); ++i) {
for (int i = 0; i < manager.getViewCount(); ++i) { if (mImageManager.getView(i) == mImageManager.getCurrentView()) continue;
if (manager.getView(i) == manager.getCurrentView()) continue; DicomImageView *overlap_view = mImageManager.getView(i);
DicomImageView * overlap_view = manager.getView(i); if (checkFusion(mImageManager.getCurrentView(), overlap_view)) {
if (checkFusionStatus(manager.getCurrentView(), overlap_view)) connect(overlap_view, &DicomImageView::onFusionWindowChange,
{ mImageManager.getCurrentView(), &DicomImageView::fusionWindowChanged);
connect(overlap_view, &DicomImageView::Signal_WindowLevelEventForFusion,
manager.getCurrentView(), &DicomImageView::fusionWindowChanged);
manager.getCurrentView()->setFusionInput(overlap_view); mImageManager.getCurrentView()->setFusionInput(overlap_view);
manager.getCurrentView()->render(); mImageManager.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)
//same series return false;
if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false; //same series
return baseSeries->IntersectWorldBounds(overlapSeries); if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false;
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();
} }
}, nullptr, nullptr, ImageViewManager::All); }, nullptr, nullptr, ImageViewManager::All);
} }
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();
} }
}, nullptr, nullptr, ImageViewManager::All); }, nullptr, nullptr, ImageViewManager::All);
} }
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);
} }
}, 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,69 +7,93 @@
#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 {
Q_OBJECT Q_OBJECT
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 clearCurrentView();
void setCurrentView(DicomImageView *view); void updateCornerInfoAll();
void emptyCurrentView();
void updateCornerInfoAll();
void updateCornerInfoPrivacy();
void activeMeasure();
void render();
void replaceViewWithSerie(const std::string& unique_info, void updateCornerInfoPrivacy();
DicomImageView* curV = nullptr);
void resetToOneView(); void activeMeasure();
//fusion void render();
void toggleViewWithFusion();
void removeCurrentViewWithFusion();
void SetInteractionMode(int InteractionMode);
void SetCurrentViewSliceOrientation(int orientation); void viewReload(const std::string &unique_info);
int GetCurrentViewSliceOrientation();
void resetLayoutToSingle();
//fusion-------------------------------------------------------------------
void switchFusion();
void loadFusion();
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
* 缩略图点击槽函数会导致当前选中的view重新load数据 * @param row
* @param tb 缩略图对象 */
* @return void viewLayoutChanged(int col, int row);
*/
void Slot_ThumbnailClickEvent(thumbnailImage* tb); void viewClicked(DicomImageView *view);
void Slot_SyncEvent(DicomImageView *view, int interactionMode, void* calldata);
/**
* @brief ViewContainerWidget::viewDoubleClicked
* 双击 view(放大缩小)
* @param view
*/
void viewDoubleClicked(DicomImageView *view);
void dragDropped(DicomImageView *view, thumbnailImage *tb);
/**
* 缩略图点击槽函数会导致当前选中的view重新load数据
* @param tb 缩略图对象
* @return
*/
void thumbnailClicked(thumbnailImage *tb);
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();