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.
//
#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) {
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);
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<thumbnailImage *>(
(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);
}
}

View File

@@ -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:

View File

@@ -1,214 +1,104 @@
#include "viewcontainerwidget.h"
#include "thumbnailImage.h"
#include "IO/DICOM/DicomLoader.h"
#include <QWidget>
#include <QGridLayout>
#include <QSettings>
#include <QFontDialog>
#include <QVTKOpenGLNativeWidget.h>
#include "Common/QGlobals.h"
#include <QDebug>
#include "qstyleoption.h"
#include "qpainter.h"
#include "cine/pqVCRToolbar.h"
#include <QMessageBox>
#include <QStyleOption>
#include <QPainter>
#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)
{
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);
viewLayoutChanged(1, 1);
}
//-------------------------------------------------------
ViewContainerWidget::~ViewContainerWidget() {
}
//-------------------------------------------------------
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 ViewContainerWidget::setInteractionMode(int InteractionMode) {
void *data = (void *) &InteractionMode;
manager.smartDo([](auto v,auto callData){
mImageManager.smartDo([](auto v, auto callData) {
int *mode = (int *) callData;
if (v->getImageViewer())
{
if (v->getImageViewer()) {
v->getImageViewer()->GetInteractorStyle()->SetInteractionModeFromEnum(*mode);
}
}, 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
if (manager.getCurrentView() != view) {
if (mImageManager.getCurrentView() != view) {
this->setCurrentView(view);
}
}
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());
}
//-------------------------------------------------------
/**
* @brief ViewContainerWidget::Slot_ViewDoubleClicked
* 双击 view(放大缩小)
* @param view
*/
void ViewContainerWidget::Slot_ViewDoubleClicked(DicomImageView *view) {
void ViewContainerWidget::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);
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);
maxed_ = true;
mMaxed = true;
}
}
//-------------------------------------------------------
/**
* @brief ViewContainerWidget::Slot_SetViewLayout
* @param col
* @param row
*/
void ViewContainerWidget::Slot_SetViewLayout(int col, int row) {
void ViewContainerWidget::viewLayoutChanged(int col, int row) {
if (!(col > 0 && row > 0)) {
return;
}
for (int i = 0; i < manager.getViewCount(); i++) {
DicomImageView *v = manager.getView(i);
for (int i = 0; i < mImageManager.getViewCount(); i++) {
DicomImageView *v = mImageManager.getView(i);
this->layout()->removeWidget(v);
}
int viewCount = col * row;
while (viewCount < manager.getViewCount()) {
DicomImageView *v = manager.getView(manager.getViewCount()-1);
while (viewCount < mImageManager.getViewCount()) {
DicomImageView *v = mImageManager.getView(mImageManager.getViewCount() - 1);
//YTC:better compare before delete
if (manager.getCurrentView() == v)
{
manager.setCurrentView(manager.getView(0));
if (mImageManager.getCurrentView() == v) {
mImageManager.setCurrentView(mImageManager.getView(0));
}
manager.remove(v);
mImageManager.remove(v);
}
//
DicomImageView *view;
@@ -222,16 +112,13 @@ void ViewContainerWidget::Slot_SetViewLayout(int col, int 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 (i * col + j < mImageManager.getViewCount()) {
view = mImageManager.getView(i * col + j);
} else {
view = addNewView();
}
if (view->IsCine())
{
if (view->IsCine()) {
//delay
pqVCRToolbar *vcr_tool = view->getVCRToolbar();
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)) {
Slot_ViewClicked(manager.getView(0));
if ((!mImageManager.getCurrentView()) && (mImageManager.getViewCount() > 0)) {
viewClicked(mImageManager.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::resizeEvent(QResizeEvent *e) {
QWidget::resizeEvent(e);
}
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)
{
void ViewContainerWidget::dragDropped(DicomImageView *view, thumbnailImage *tb) {
auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view);
setCurrentView(view);
viewReload(serie_info->GetUniqueID());
}
void ViewContainerWidget::Slot_ThumbnailClickEvent(thumbnailImage* tb)
{
DicomImageView *view = manager.getCurrentView();
if (nullptr == view)
{
return;
}
void ViewContainerWidget::thumbnailClicked(thumbnailImage *tb) {
auto serie_info = tb->getSeriesInfo();
replaceViewWithSerie(serie_info->GetUniqueID(), view);
manager.setCurrentView(view);
viewReload(serie_info->GetUniqueID());
}
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();
}
curV->unloadFusion();
void ViewContainerWidget::viewReload(const std::string &unique_info) {
if (!mImageManager.getCurrentView()) return;
mImageManager.getCurrentView()->unloadFusion();
DicomLoader *helper = DicomLoader::GetInstance();
curV->loadSeries(helper->getSeriesImageSet(uniqueid));
curV->render();
mImageManager.getCurrentView()->loadSeries(helper->getSeriesImageSet(unique_info));
mImageManager.getCurrentView()->render();
}
void ViewContainerWidget::toggleViewWithFusion()
{
if (manager.getCurrentView())
{
//view layout about------------------------------------------------------------
DicomImageView *ViewContainerWidget::addNewView() {
DicomImageView *v = new DicomImageView(this);
if (manager.getCurrentView()->hasSeries() && manager.getCurrentView()->isFusion())
{
removeCurrentViewWithFusion();
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);
}
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()
{
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();
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)
{
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;
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) {
mImageManager.smartDo([](auto v, auto calldata) {
if (v->hasSeries()) {
v->updateCornerInfoAll();
}
@@ -398,7 +256,7 @@ void ViewContainerWidget::updateCornerInfoAll() {
}
void ViewContainerWidget::updateCornerInfoPrivacy() {
manager.smartDo([](auto v, auto calldata) {
mImageManager.smartDo([](auto v, auto calldata) {
if (v->hasSeries()) {
v->updateCornerInfoPrivacy();
}
@@ -406,16 +264,20 @@ void ViewContainerWidget::updateCornerInfoPrivacy() {
}
void ViewContainerWidget::render() {
manager.smartDo([](auto v, auto calldata) {
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) {
mImageManager.smartDo([](auto v, auto) {
if (v->hasSeries()) {
Measure *measure = MeasureFactory::getMeasure((AnnotationActorType) MeasureHelper::getMeasureType());
v->activeMeasure(measure);
@@ -423,11 +285,13 @@ void ViewContainerWidget::activeMeasure() {
}, 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();;
}

View File

@@ -1,4 +1,5 @@
#pragma once
#ifndef OMEGAV_VIEW_CONTAINER_WIDGET_H
#define OMEGAV_VIEW_CONTAINER_WIDGET_H
#include <QFrame>
#include <QScrollBar>
#include "Common/QGlobals.h"
@@ -6,8 +7,11 @@
#include "UI/Manager/ImageViewManager.h"
class QGridLayout;
class DicomImageView;
class SeriesImageSet;
class Measure;
class ViewContainerWidget : public QFrame {
@@ -16,59 +20,80 @@ class ViewContainerWidget : public QFrame {
public:
explicit ViewContainerWidget(QWidget *parent = nullptr);
~ViewContainerWidget();
DicomImageView *getCurrentView();
DicomImageView* getNextView();
QList<DicomImageView*>& getViewList() ;
void setCurrentView(DicomImageView *view);
void emptyCurrentView();
void clearCurrentView();
void updateCornerInfoAll();
void updateCornerInfoPrivacy();
void activeMeasure();
void render();
void replaceViewWithSerie(const std::string& unique_info,
DicomImageView* curV = nullptr);
void viewReload(const std::string &unique_info);
void resetToOneView();
void resetLayoutToSingle();
//fusion
void toggleViewWithFusion();
void removeCurrentViewWithFusion();
void SetInteractionMode(int InteractionMode);
//fusion-------------------------------------------------------------------
void switchFusion();
void SetCurrentViewSliceOrientation(int orientation);
int GetCurrentViewSliceOrientation();
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);
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 Slot_ThumbnailClickEvent(thumbnailImage* tb);
void Slot_SyncEvent(DicomImageView *view, int interactionMode, void* calldata);
void thumbnailClicked(thumbnailImage *tb);
void viewSynced(DicomImageView *view, int interactionMode, void *calldata);
protected:
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<DicomImageView*> view_list_;
DicomImageView *current_view_ = nullptr;
ImageViewManager manager;
bool maxed_ = false;
DicomImageView *addNewView();
ImageViewManager mImageManager;
bool mMaxed = false;
};
#endif

View File

@@ -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();