From 6292db3b6ce03b9d53d2b63986b8e33b9b7617cc Mon Sep 17 00:00:00 2001 From: Krad Date: Wed, 6 Jul 2022 09:32:56 +0800 Subject: [PATCH] Refactor dicomimageview and viewcontainerwidget. --- src/src/UI/Manager/ImageViewManager.cpp | 79 ++- src/src/UI/Widget/dicomimageview.cpp | 38 +- src/src/UI/Widget/dicomimageview.h | 16 +- src/src/UI/Widget/viewcontainerwidget.cpp | 560 ++++++++-------------- src/src/UI/Widget/viewcontainerwidget.h | 115 +++-- src/src/UI/Window/QDicomViewer.cpp | 28 +- 6 files changed, 400 insertions(+), 436 deletions(-) diff --git a/src/src/UI/Manager/ImageViewManager.cpp b/src/src/UI/Manager/ImageViewManager.cpp index 068780f..86264a5 100644 --- a/src/src/UI/Manager/ImageViewManager.cpp +++ b/src/src/UI/Manager/ImageViewManager.cpp @@ -1,9 +1,20 @@ // // Created by Krad on 2022/3/9. // - #include "ImageViewManager.h" -#include "algorithm" + +#include +#include +#include +#include +#include +#include + +#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) { 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; + } +} \ No newline at end of file diff --git a/src/src/UI/Widget/dicomimageview.cpp b/src/src/UI/Widget/dicomimageview.cpp index 446fbc6..9df84e2 100644 --- a/src/src/UI/Widget/dicomimageview.cpp +++ b/src/src/UI/Widget/dicomimageview.cpp @@ -93,7 +93,7 @@ void DicomImageView::initScrollbar() { mScrollBar->setVisible(true); if (!mIsSlotInited) { connect(mScrollBar, &QScrollBar::valueChanged, this, &DicomImageView::scrollBarValueChanged); - connect(this, &DicomImageView::Signal_Transformation, this, &DicomImageView::imageTransformed); + connect(this, &DicomImageView::onTransform, this, &DicomImageView::imageTransformed); mIsSlotInited = true; } } @@ -193,11 +193,11 @@ void DicomImageView::scrollBarValueChanged(int slice) { } void DicomImageView::viewCleared() { - emit Signal_ViewEmpty(this); + emit onViewClear(this); } void DicomImageView::doubleClicked() { - emit Signal_viewDoubleclicked(this); + emit onViewDoubleClick(this); } void DicomImageView::fusionWindowChanged(double level, double width) { @@ -214,7 +214,7 @@ void DicomImageView::imageTransformed() { } void DicomImageView::clicked() { - emit Signal_ViewClicked(this); + emit onViewClick(this); } //Widget event---------------------------------------------------------------- @@ -246,7 +246,7 @@ void DicomImageView::wheelEvent(QWheelEvent *event) { void DicomImageView::mousePressEvent(QMouseEvent *event) { - emit Signal_ViewClicked(this); + emit onViewClick(this); } void DicomImageView::resizeEvent(QResizeEvent *event) { @@ -285,7 +285,7 @@ void DicomImageView::dropEvent(QDropEvent *e) { thumbnailImage *tb = qobject_cast( (QObject *) (e->mimeData()->text().toULongLong())); if (tb) { - emit Signal_DragDropEvent(this, tb); + emit onDragDrop(this, tb); } } } @@ -342,7 +342,7 @@ void DicomImageView::setFusionOpacity(double percent) { void DicomImageView::unloadFusion() { if (hasSeries()) { if (isFusion()) { - disconnect(mOverlayView, &DicomImageView::Signal_WindowLevelEventForFusion, + disconnect(mOverlayView, &DicomImageView::onFusionWindowChange, this, &DicomImageView::fusionWindowChanged); this->clearFusionContext(); @@ -351,7 +351,7 @@ void DicomImageView::unloadFusion() { } if (IsOverlay()) { - disconnect(this, &DicomImageView::Signal_WindowLevelEventForFusion, + disconnect(this, &DicomImageView::onFusionWindowChange, mBaseView, &DicomImageView::fusionWindowChanged); mBaseView->clearFusionContext(); @@ -371,7 +371,7 @@ void DicomImageView::clearFusionContext() { //Callbacks------------------------------------------------------------------------------------ void DicomImageView::updateWindowLevelCb() { 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) { @@ -393,7 +393,7 @@ void DicomImageView::scalarEventCb(vtkObject *, unsigned long eventId, void *cal } void DicomImageView::doubleclickedEventCb() { - emit Signal_viewDoubleclicked(this); + emit onViewDoubleClick(this); } //TODO:重新匹配该函数,部分逻辑可以直接保留,需要注意Endxxx系列事件不是仅仅为了sync设计的 @@ -402,21 +402,21 @@ void DicomImageView::syncEventFunc(vtkObject *, unsigned long eid, void *calldat int *r = (int *) calldata; switch (eid) { case (vtkCommand::EventIds::EndPanEvent): - this->Signal_SyncEvent(this, VTKIS_IMAGE_PAN, calldata); + this->onSync(this, VTKIS_IMAGE_PAN, calldata); break; case (vtkCommand::EventIds::EndWindowLevelEvent): //update corner info through callback - this->Signal_SyncEvent(this, VTKIS_IMAGE_WINDOWLEVEL, calldata); + this->onSync(this, VTKIS_IMAGE_WINDOWLEVEL, calldata); break; case (ActorDraggableInteractorStyle::DraggableStyleEvents::EndDollyEvent): - this->Signal_SyncEvent(this, VTKIS_IMAGE_ZOOM, calldata); + this->onSync(this, VTKIS_IMAGE_ZOOM, calldata); break; case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): { mScrollBar->SetValueSilently(r[0]); //invoke event double focusPoint[3] = {.0, .0, .0}; mImageViewer->GetSlicePoint(focusPoint); - this->Signal_SyncEvent(this, VTKIS_IMAGE_SLICING, focusPoint); + this->onSync(this, VTKIS_IMAGE_SLICING, focusPoint); break; } default: @@ -500,7 +500,7 @@ void DicomImageView::setWindowLevel(double level, double width) { //You have to call updateConerInfo manually //only mouse event can rely on callback mImageViewer->UpdateCornerInfo(BOTTOM_RIGHT); - emit Signal_WindowLevelEventForFusion(level, width); + emit onFusionWindowChange(level, width); } } @@ -538,7 +538,7 @@ void DicomImageView::hFlipImage() { mImageViewer->SetSlice(slice); mImageViewer->GetRenderWindow()->Render(); - emit Signal_Transformation(H_FLIP); + emit onTransform(H_FLIP); } } @@ -558,7 +558,7 @@ void DicomImageView::vFlipImage() { mImageViewer->GetRenderer()->ResetCameraClippingRange(); mImageViewer->SetSlice(slice); 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->SetSlice(slice); // mImageViewer->GetRenderWindow()->Render(); - emit Signal_Transformation(operation); + emit onTransform(operation); } } @@ -594,7 +594,7 @@ void DicomImageView::ClearTransformations() { mImageViewer->SetSlice(slice); //Render mImageViewer->GetRenderWindow()->Render(); - emit Signal_Transformation(CLEAR); + emit onTransform(CLEAR); } } diff --git a/src/src/UI/Widget/dicomimageview.h b/src/src/UI/Widget/dicomimageview.h index 81d037f..ace92ab 100644 --- a/src/src/UI/Widget/dicomimageview.h +++ b/src/src/UI/Widget/dicomimageview.h @@ -154,7 +154,7 @@ public: return this->mImageViewer->GetWorldSliceOrientation() == view->mImageViewer->GetWorldSliceOrientation(); } - void SyncSlicePoint(double *point) { + void syncSlicePoint(double *point) { mImageViewer->SyncSlicePoint(point); mImageViewer->Render(); } @@ -163,19 +163,19 @@ public: 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: diff --git a/src/src/UI/Widget/viewcontainerwidget.cpp b/src/src/UI/Widget/viewcontainerwidget.cpp index 88cf040..89b252e 100644 --- a/src/src/UI/Widget/viewcontainerwidget.cpp +++ b/src/src/UI/Widget/viewcontainerwidget.cpp @@ -1,433 +1,297 @@ #include "viewcontainerwidget.h" -#include "thumbnailImage.h" -#include "IO/DICOM/DicomLoader.h" -#include -#include -#include + #include #include -#include "Common/QGlobals.h" #include -#include "qstyleoption.h" -#include "qpainter.h" -#include "cine/pqVCRToolbar.h" #include +#include +#include + #include "Interaction/ActorDraggableInteractorStyle.h" #include "Rendering/Measure/MeasureFactory.h" -//------------------------------------------------------- +#include "IO/DICOM/DicomLoader.h" +#include "thumbnailImage.h" +#include "cine/pqVCRToolbar.h" - -ViewContainerWidget::ViewContainerWidget(QWidget *parent) :QFrame(parent) -{ - QGridLayout * layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - this->setLayout(layout); - Slot_SetViewLayout(1, 1); +ViewContainerWidget::ViewContainerWidget(QWidget *parent) : QFrame(parent) { + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + this->setLayout(layout); + viewLayoutChanged(1, 1); } -//------------------------------------------------------- ViewContainerWidget::~ViewContainerWidget() { } -//------------------------------------------------------- -QList& 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; - manager.smartDo([](auto v,auto callData){ - int* mode = (int *)callData; - if (v->getImageViewer()) - { +void ViewContainerWidget::setInteractionMode(int InteractionMode) { + void *data = (void *) &InteractionMode; + mImageManager.smartDo([](auto v, auto callData) { + int *mode = (int *) callData; + if (v->getImageViewer()) { v->getImageViewer()->GetInteractorStyle()->SetInteractionModeFromEnum(*mode); } }, nullptr, data, ImageViewManager::All); } -void ViewContainerWidget::Slot_ViewClicked(DicomImageView *view) { - //set current_view - if (manager.getCurrentView() != view) { - this->setCurrentView(view); - } - +//Current view about----------------------------------------------------------- +DicomImageView *ViewContainerWidget::getCurrentView() { + return mImageManager.getCurrentView(); } void ViewContainerWidget::setCurrentView(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()); + //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()); } -//------------------------------------------------------- -/** - * @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::clearCurrentView() { + viewCleared(mImageManager.getCurrentView()); } -//------------------------------------------------------- -/** - * @brief ViewContainerWidget::Slot_SetViewLayout - * @param col - * @param row - */ -void ViewContainerWidget::Slot_SetViewLayout(int col, int row) { +void ViewContainerWidget::viewClicked(DicomImageView *view) { + //set current_view + if (mImageManager.getCurrentView() != view) { + this->setCurrentView(view); + } - 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(this->layout()); - layout->addWidget(view, i, j); - - } - } - if ((!manager.getCurrentView()) && (manager.getViewCount()>0)) { - Slot_ViewClicked(manager.getView(0)); - } } -//------------------------------------------------------- -DicomImageView *ViewContainerWidget::createImageView(QWidget* parent) { - 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::viewDoubleClicked(DicomImageView *view) { + if (!view) { + return; + } + if (mMaxed) { + mImageManager.smartDo([](auto v, auto callData) { v->setVisible(true); }, nullptr, nullptr, + ImageViewManager::All); + mMaxed = false; + } else { + mImageManager.smartDo([](auto v, auto callData) { v->setVisible(false); }, nullptr, nullptr, + ImageViewManager::AllExceptSelf); + view->setVisible(true); + mMaxed = true; + } } -void ViewContainerWidget::resizeEvent(QResizeEvent *e) { - QWidget::resizeEvent(e); +void ViewContainerWidget::viewLayoutChanged(int col, int row) { + + 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(this->layout()); + layout->addWidget(view, i, j); + + } + } + if ((!mImageManager.getCurrentView()) && (mImageManager.getViewCount() > 0)) { + viewClicked(mImageManager.getView(0)); + } } -void ViewContainerWidget::emptyCurrentView() -{ - Slot_ViewEmpty(manager.getCurrentView()); -} - - -void ViewContainerWidget::Slot_ViewEmpty(DicomImageView *view) -{ - if (view != nullptr) - { +void ViewContainerWidget::viewCleared(DicomImageView *view) { + if (view != nullptr) { 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) -{ - if (!curV) - { - curV= manager.getCurrentView(); +void ViewContainerWidget::dragDropped(DicomImageView *view, thumbnailImage *tb) { + auto serie_info = tb->getSeriesInfo(); + setCurrentView(view); + viewReload(serie_info->GetUniqueID()); + +} + +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(); - DicomLoader *helper = DicomLoader::GetInstance(); - curV->loadSeries(helper->getSeriesImageSet(uniqueid)); - curV->render(); + DicomImageView *v = mImageManager.getView(0); + mImageManager.clear(); + mImageManager.add(v); + mImageManager.setCurrentView(v); } -void ViewContainerWidget::toggleViewWithFusion() -{ - if (manager.getCurrentView()) - { - - if (manager.getCurrentView()->hasSeries() && manager.getCurrentView()->isFusion()) - { - removeCurrentViewWithFusion(); - } - else - { - replaceViewWithFusion(); - } - } +//fusion about----------------------------------------------------------------- +void ViewContainerWidget::switchFusion() { + if (mImageManager.getCurrentView()) { + if (mImageManager.getCurrentView()->hasSeries() && mImageManager.getCurrentView()->isFusion()) { + unloadFusion(); + } else { + loadFusion(); + } + } } -void ViewContainerWidget::replaceViewWithFusion() -{ - 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); +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); - manager.getCurrentView()->setFusionInput(overlap_view); - manager.getCurrentView()->render(); + mImageManager.getCurrentView()->setFusionInput(overlap_view); + mImageManager.getCurrentView()->render(); return; } } QMessageBox::information(this, "Warning", "Invalid Fusion!"); } -void ViewContainerWidget::removeCurrentViewWithFusion() -{ - if (manager.getCurrentView()) { - manager.getCurrentView()->unloadFusion(); - } + +void ViewContainerWidget::unloadFusion() { + if (mImageManager.getCurrentView()) { + mImageManager.getCurrentView()->unloadFusion(); + } } -bool ViewContainerWidget::checkFusionStatus(DicomImageView *base, DicomImageView* overlap) -{ - SeriesImageSet* baseSeries = base->getSeriesInstance(); - SeriesImageSet* overlapSeries = overlap->getSeriesInstance(); - // no data - if (!base->hasSeries() || !overlap->hasSeries()) return false; +bool ViewContainerWidget::checkFusion(DicomImageView *base, DicomImageView *overlap) { + SeriesImageSet *baseSeries = base->getSeriesInstance(); + SeriesImageSet *overlapSeries = overlap->getSeriesInstance(); + // no data + if (!base->hasSeries() || !overlap->hasSeries()) return false; // diff study if (baseSeries->getStudyUID() == nullptr || - strcmp(baseSeries->getStudyUID(), overlapSeries->getStudyUID())!=0) return false; - //same series - if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false; - return baseSeries->IntersectWorldBounds(overlapSeries); + strcmp(baseSeries->getStudyUID(), overlapSeries->getStudyUID()) != 0) + return false; + //same series + if (baseSeries->GetSeriesNumber() == overlapSeries->GetSeriesNumber()) return false; + return baseSeries->IntersectWorldBounds(overlapSeries); } +//Corner about----------------------------------------------------------------- void ViewContainerWidget::updateCornerInfoAll() { - manager.smartDo([](auto v, auto calldata) { - if (v->hasSeries()){ + mImageManager.smartDo([](auto v, auto calldata) { + if (v->hasSeries()) { v->updateCornerInfoAll(); } }, nullptr, nullptr, ImageViewManager::All); } void ViewContainerWidget::updateCornerInfoPrivacy() { - manager.smartDo([](auto v, auto calldata) { - if (v->hasSeries()){ + mImageManager.smartDo([](auto v, auto calldata) { + if (v->hasSeries()) { v->updateCornerInfoPrivacy(); } }, nullptr, nullptr, ImageViewManager::All); } void ViewContainerWidget::render() { - manager.smartDo([](auto v, auto calldata) { - if (v->hasSeries()){ + mImageManager.smartDo([](auto v, auto) { + if (v->hasSeries()) { v->render(); } }, nullptr, nullptr, ImageViewManager::All); } +void ViewContainerWidget::resizeEvent(QResizeEvent *e) { + QWidget::resizeEvent(e); +} + void ViewContainerWidget::activeMeasure() { - manager.smartDo([](auto v, auto calldata) { - if (v->hasSeries()){ - Measure* measure = MeasureFactory::getMeasure((AnnotationActorType)MeasureHelper::getMeasureType()); + mImageManager.smartDo([](auto v, auto) { + if (v->hasSeries()) { + Measure *measure = MeasureFactory::getMeasure((AnnotationActorType) MeasureHelper::getMeasureType()); v->activeMeasure(measure); } }, nullptr, nullptr, ImageViewManager::All); } -void ViewContainerWidget::SetCurrentViewSliceOrientation(int type) { - manager.getCurrentView()->getSliceOrientation(type); +void ViewContainerWidget::setCurrentViewSliceOrientation(int orientation) { + mImageManager.getCurrentView()->getSliceOrientation(orientation); } -int ViewContainerWidget::GetCurrentViewSliceOrientation() { - return manager.getCurrentView()->getSliceOrientation();; +int ViewContainerWidget::getCurrentViewSliceOrientation() { + return mImageManager.getCurrentView()->getSliceOrientation();; } + + diff --git a/src/src/UI/Widget/viewcontainerwidget.h b/src/src/UI/Widget/viewcontainerwidget.h index 8e7b959..f64e246 100644 --- a/src/src/UI/Widget/viewcontainerwidget.h +++ b/src/src/UI/Widget/viewcontainerwidget.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef OMEGAV_VIEW_CONTAINER_WIDGET_H +#define OMEGAV_VIEW_CONTAINER_WIDGET_H #include #include #include "Common/QGlobals.h" @@ -6,69 +7,93 @@ #include "UI/Manager/ImageViewManager.h" class QGridLayout; + class DicomImageView; + class SeriesImageSet; + class Measure; class ViewContainerWidget : public QFrame { - Q_OBJECT +Q_OBJECT public: - explicit ViewContainerWidget(QWidget *parent = nullptr); - ~ViewContainerWidget(); + explicit ViewContainerWidget(QWidget *parent = nullptr); + ~ViewContainerWidget(); - DicomImageView* getCurrentView(); - DicomImageView* getNextView(); - QList& getViewList() ; + DicomImageView *getCurrentView(); - + void setCurrentView(DicomImageView *view); - void setCurrentView(DicomImageView *view); - void emptyCurrentView(); - void updateCornerInfoAll(); - void updateCornerInfoPrivacy(); - void activeMeasure(); - void render(); + void clearCurrentView(); - void replaceViewWithSerie(const std::string& unique_info, - DicomImageView* curV = nullptr); + void updateCornerInfoAll(); - void resetToOneView(); + void updateCornerInfoPrivacy(); - //fusion - void toggleViewWithFusion(); - void removeCurrentViewWithFusion(); - void SetInteractionMode(int InteractionMode); + void activeMeasure(); - void SetCurrentViewSliceOrientation(int orientation); - int GetCurrentViewSliceOrientation(); + void render(); + + void viewReload(const std::string &unique_info); + + void resetLayoutToSingle(); + + //fusion------------------------------------------------------------------- + void switchFusion(); + + void loadFusion(); + + void unloadFusion(); + + void setInteractionMode(int InteractionMode); + + void setCurrentViewSliceOrientation(int orientation); + + int getCurrentViewSliceOrientation(); signals: - void Signal_NotifyThumbnail(DicomImageView *view); + void onThumbnailTrigger(DicomImageView *view); public slots: - void Slot_ViewEmpty(DicomImageView *view); - void Slot_SetViewLayout(int col, int row); - void Slot_ViewClicked(DicomImageView *view); - void Slot_ViewDoubleClicked(DicomImageView *view); - void Slot_DragDropEvent(DicomImageView *view, thumbnailImage* tb); - /** - * 缩略图点击槽函数,会导致当前选中的view重新load数据 - * @param tb 缩略图对象 - * @return - */ - void Slot_ThumbnailClickEvent(thumbnailImage* tb); - void Slot_SyncEvent(DicomImageView *view, int interactionMode, void* calldata); + + void viewCleared(DicomImageView *view); + + /** + * @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数据 + * @param tb 缩略图对象 + * @return + */ + void thumbnailClicked(thumbnailImage *tb); + + void viewSynced(DicomImageView *view, int interactionMode, void *calldata); protected: - void resizeEvent(QResizeEvent *e); + + void resizeEvent(QResizeEvent *e); private: - //fusion - void replaceViewWithFusion(); /** * 判断是否能fusion,判断依据为是否相同Study, @@ -78,11 +103,11 @@ private: * @param overlap 覆盖数据源View * @return */ - bool checkFusionStatus(DicomImageView *base, DicomImageView* overlap); + bool checkFusion(DicomImageView *base, DicomImageView *overlap); - DicomImageView *createImageView(QWidget* parent); - QList view_list_; - DicomImageView *current_view_ = nullptr; - ImageViewManager manager; - bool maxed_ = false; + DicomImageView *addNewView(); + + ImageViewManager mImageManager; + bool mMaxed = false; }; +#endif diff --git a/src/src/UI/Window/QDicomViewer.cpp b/src/src/UI/Window/QDicomViewer.cpp index 8a7668f..209791a 100644 --- a/src/src/UI/Window/QDicomViewer.cpp +++ b/src/src/UI/Window/QDicomViewer.cpp @@ -205,7 +205,7 @@ void QDicomViewer::createToolButton() this->SetupCloseTool(btnclose); 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")); connect(fusionBtn, &QToolButton::clicked, this, [&] { - ui->viewContainer->toggleViewWithFusion(); + ui->viewContainer->switchFusion(); }); QMenu* m; m = new QMenu(this); m->addAction(tr("Reset Fusion"), this, [&] { - ui->viewContainer->removeCurrentViewWithFusion(); + ui->viewContainer->unloadFusion(); }); fusionBtn->setPopupMode(QToolButton::MenuButtonPopup); fusionBtn->setMenu(m); @@ -512,7 +512,7 @@ void QDicomViewer::SetupSliceTool(QToolButton* sliceBtn) sliceBtn->setToolTip(QString("Browse series")); connect(sliceBtn, &QToolButton::clicked, this, [&] { //ui->viewContainer->setLeftButtonState(VTKIS_SLICE); - ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_SLICING); + ui->viewContainer->setInteractionMode(VTKIS_IMAGE_SLICING); }); } //视窗操作,pan @@ -521,7 +521,7 @@ void QDicomViewer::SetupPanTool(QToolButton* panBtn) panBtn->setToolTip(QString("Pan image")); connect(panBtn, &QToolButton::clicked, this, [&] { //ui->viewContainer->setLeftButtonState(VTKIS_PAN); - ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_PAN); + ui->viewContainer->setInteractionMode(VTKIS_IMAGE_PAN); }); } //视窗操作,zoom @@ -530,7 +530,7 @@ void QDicomViewer::SetupZoomTool(QToolButton* zoomBtn) zoomBtn->setToolTip(QString("Zoom image")); connect(zoomBtn, &QToolButton::clicked, this, [&] { //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")); connect(winlevelBtn, &QToolButton::clicked, this, [&] { //ui->viewContainer->setLeftButtonState(VTKIS_WINDOW_LEVEL); - ui->viewContainer->SetInteractionMode(VTKIS_IMAGE_WINDOWLEVEL); + ui->viewContainer->setInteractionMode(VTKIS_IMAGE_WINDOWLEVEL); }); // Menu @@ -579,7 +579,7 @@ void QDicomViewer::SetupEmptyTool(QToolButton* emptyBtn) { emptyBtn->setToolTip(QString("Delete current series")); connect(emptyBtn, &QToolButton::clicked, this, [&] { - ui->viewContainer->emptyCurrentView(); + ui->viewContainer->clearCurrentView(); }); } @@ -843,7 +843,7 @@ void QDicomViewer::SetupGridTool(QToolButton* gridBtn) { //qDebug() << &gridBtn; GridPopWidget* gpw = new GridPopWidget(gridBtn); 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->show(); }); @@ -852,19 +852,19 @@ void QDicomViewer::SetupGridTool(QToolButton* gridBtn) { void QDicomViewer::SetupConnections() { //通知左侧的缩略图bar ,当前选中series的变换 - connect(ui->viewContainer, &ViewContainerWidget::Signal_NotifyThumbnail, + connect(ui->viewContainer, &ViewContainerWidget::onThumbnailTrigger, ui->thumbnailBar, &ThumbnailBarWidget::Slot_setCurrentThumbnail); //通知右侧显示区域,当前有series被点击 connect(ui->thumbnailBar, &ThumbnailBarWidget::Signal_ThumbClicked, - ui->viewContainer, &ViewContainerWidget::Slot_ThumbnailClickEvent); + ui->viewContainer, &ViewContainerWidget::thumbnailClicked); connect(ui->toolBar,&QToolBar::visibilityChanged, this, &QDicomViewer::Slot_ToolbarVisibilityChanged); - //connect(ui->viewContainer, SIGNAL(Signal_NotifyThumbnail(DicomImageView*)), + //connect(ui->viewContainer, SIGNAL(onThumbnailTrigger(DicomImageView*)), // ui->vcr_toolbar, SLOT(setImageView(DicomImageView*))); //connect(ui->thumbnailBar, SIGNAL(Signal_CopyDicomView(SeriesInfo_t*)), @@ -896,14 +896,14 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode displayThumbnailBar(true); //必须首先重置成1个窗口的布局 - ui->viewContainer->resetToOneView(); + ui->viewContainer->resetLayoutToSingle(); DicomLoader *helper = DicomLoader::GetInstance(); helper->reset(); //load image and tag helper->readTags(dicomName, openMode); auto unique = helper->getDefaultUniqueID(); - ui->viewContainer->replaceViewWithSerie(unique); + ui->viewContainer->viewReload(unique); //view clicked will notify thumbnailbar update ui->thumbnailBar->updateThumbnailBar();