From cc4326ded302e89b05490b24fd6a83a46331fb9d Mon Sep 17 00:00:00 2001 From: Krad Date: Fri, 23 Sep 2022 13:13:41 +0800 Subject: [PATCH] Add UI for DIDKIT. --- DIDKit/App/DICOMPropertiesStore.cpp | 66 +++++++ DIDKit/App/DICOMPropertiesStore.h | 38 ++++ DIDKit/App/DIDMainWindow.cpp | 101 +++++++++- DIDKit/App/DIDMainWindow.h | 44 +++-- DIDKit/App/DIDMainWindow.ui | 40 ++++ DIDKit/App/MenuAction/ClearFileAction.cpp | 19 ++ DIDKit/App/MenuAction/ClearFileAction.h | 21 ++ DIDKit/App/MenuAction/ClearPropertyAction.cpp | 20 ++ DIDKit/App/MenuAction/ClearPropertyAction.h | 21 ++ DIDKit/App/MenuAction/ExitAction.cpp | 17 ++ DIDKit/App/MenuAction/ExitAction.h | 16 ++ .../MenuAction/GetPacsConfigDialogAction.cpp | 20 ++ .../MenuAction/GetPacsConfigDialogAction.h | 21 ++ DIDKit/App/MenuAction/OpenDirAction.cpp | 41 ++++ DIDKit/App/MenuAction/OpenDirAction.h | 18 ++ DIDKit/App/MenuAction/OpenFileAction.cpp | 41 ++++ DIDKit/App/MenuAction/OpenFileAction.h | 18 ++ DIDKit/App/MenuAction/OpenWorkSpaceAction.cpp | 22 +++ DIDKit/App/MenuAction/OpenWorkSpaceAction.h | 16 ++ DIDKit/App/Model/FileItem.cpp | 82 ++++++++ DIDKit/App/Model/FileItem.h | 37 ++++ DIDKit/App/Model/FileItemAction.cpp | 24 +++ DIDKit/App/Model/FileItemAction.h | 18 ++ DIDKit/App/Model/FileModel.cpp | 180 ++++++++++++++++++ DIDKit/App/Model/FileModel.h | 35 ++++ DIDKit/App/Model/PropertyTableModel.cpp | 22 +++ DIDKit/App/Model/PropertyTableModel.h | 15 ++ DIDKit/App/app.cpp | 48 ++--- DIDKit/CMakeLists.txt | 14 +- src/src/Common/ImageSetStore.cpp | 2 + .../IO/DICOM/ExtendMedicalImageProperties.cpp | 6 +- 31 files changed, 1014 insertions(+), 69 deletions(-) create mode 100644 DIDKit/App/DICOMPropertiesStore.cpp create mode 100644 DIDKit/App/DICOMPropertiesStore.h create mode 100644 DIDKit/App/DIDMainWindow.ui create mode 100644 DIDKit/App/MenuAction/ClearFileAction.cpp create mode 100644 DIDKit/App/MenuAction/ClearFileAction.h create mode 100644 DIDKit/App/MenuAction/ClearPropertyAction.cpp create mode 100644 DIDKit/App/MenuAction/ClearPropertyAction.h create mode 100644 DIDKit/App/MenuAction/ExitAction.cpp create mode 100644 DIDKit/App/MenuAction/ExitAction.h create mode 100644 DIDKit/App/MenuAction/GetPacsConfigDialogAction.cpp create mode 100644 DIDKit/App/MenuAction/GetPacsConfigDialogAction.h create mode 100644 DIDKit/App/MenuAction/OpenDirAction.cpp create mode 100644 DIDKit/App/MenuAction/OpenDirAction.h create mode 100644 DIDKit/App/MenuAction/OpenFileAction.cpp create mode 100644 DIDKit/App/MenuAction/OpenFileAction.h create mode 100644 DIDKit/App/MenuAction/OpenWorkSpaceAction.cpp create mode 100644 DIDKit/App/MenuAction/OpenWorkSpaceAction.h create mode 100644 DIDKit/App/Model/FileItem.cpp create mode 100644 DIDKit/App/Model/FileItem.h create mode 100644 DIDKit/App/Model/FileItemAction.cpp create mode 100644 DIDKit/App/Model/FileItemAction.h create mode 100644 DIDKit/App/Model/FileModel.cpp create mode 100644 DIDKit/App/Model/FileModel.h create mode 100644 DIDKit/App/Model/PropertyTableModel.cpp create mode 100644 DIDKit/App/Model/PropertyTableModel.h diff --git a/DIDKit/App/DICOMPropertiesStore.cpp b/DIDKit/App/DICOMPropertiesStore.cpp new file mode 100644 index 0000000..534ba3d --- /dev/null +++ b/DIDKit/App/DICOMPropertiesStore.cpp @@ -0,0 +1,66 @@ +// +// Created by Krad on 2022/9/23. +// + +#include "DICOMPropertiesStore.h" + +#include "IO/DICOM/ExtendMedicalImageProperties.h" + +void DICOMPropertiesStore::addProperty(ExtendMedicalImageProperties *property) { + std::string patient_name = property->GetPatientName(); + std::string study_uid = property->GetStudyUID(); + std::string series_uid = property->GetSeriesUID(); + //patient level + PatientInfo_t* patient = nullptr; + //get from store + if (m_patients.count(patient_name)>0){ + patient = m_patients[patient_name]; + } + else{ + //create new + patient = new PatientInfo_t(); + patient->patient_name = property->GetPatientName(); + patient->birth_date = property->GetPatientBirthDate(); + patient->studies = new StudiesMapType(); + m_patients[property->GetPatientID()] = patient; + } + StudyInfo_t* study = nullptr; + //get from store + if (patient->studies->count(study_uid)>0){ + study = patient->studies->at(study_uid); + } + else{ + //create new + study = new StudyInfo_t(); + patient->studies->insert({study_uid, study}); + study->study_description = property->GetStudyDescription(); + study->study_date = property->GetStudyDate(); + study->study_time = property->GetStudyTime(); + study->series = new SeriesMapType(); + } + //TODO:need add Image set logic + if (study->series->count(series_uid)>0){ + study->series->at(series_uid)->insert({property->GetUniqueID(),property}); + property->Register(m_Holder); + } + else { + ImageSetMapType* v = new ImageSetMapType; + v->insert({property->GetUniqueID(),property}); + study->series->insert({series_uid,v}); + property->Register(m_Holder); + } +} + +void DICOMPropertiesStore::reset() { + m_patients.clear(); + if (m_Holder)m_Holder->Delete(); + m_Holder = vtkObject::New(); +} + +DICOMPropertiesStore::DICOMPropertiesStore() { + m_Holder = vtkObject::New(); +} + +DICOMPropertiesStore::~DICOMPropertiesStore() { + if (m_Holder)m_Holder->Delete(); +} diff --git a/DIDKit/App/DICOMPropertiesStore.h b/DIDKit/App/DICOMPropertiesStore.h new file mode 100644 index 0000000..0075d0e --- /dev/null +++ b/DIDKit/App/DICOMPropertiesStore.h @@ -0,0 +1,38 @@ +// +// Created by Krad on 2022/9/23. +// + +#ifndef OMEGAV_DICOMPROPERTIESSTORE_H +#define OMEGAV_DICOMPROPERTIESSTORE_H + +#include +#include +#include +#include + +#include "IO/Common/DICOMTypes.h" + +class ExtendMedicalImageProperties; + +class DICOMPropertiesStore { +public: + static DICOMPropertiesStore *GetInstance() { + static DICOMPropertiesStore store; + return &store; + } + + PatientsMapType* getPatientsList() { + return &m_patients; + } + + void addProperty(ExtendMedicalImageProperties *property); + + void reset(); + +private: + DICOMPropertiesStore(); + ~DICOMPropertiesStore(); + PatientsMapType m_patients; + vtkObject *m_Holder; +}; +#endif //OMEGAV_DICOMPROPERTIESSTORE_H diff --git a/DIDKit/App/DIDMainWindow.cpp b/DIDKit/App/DIDMainWindow.cpp index 9049da5..290e311 100644 --- a/DIDKit/App/DIDMainWindow.cpp +++ b/DIDKit/App/DIDMainWindow.cpp @@ -1,15 +1,96 @@ -// -// Created by Krad on 2022/9/20. -// - #include "DIDMainWindow.h" -#include "PACS/Widget/ImportWidget.h" +#include "ui_DIDMainWindow.h" -DIDMainWindow::DIDMainWindow(QWidget *parent) { - auto m_import = new ImportWidget(this); - m_import->show(); +#include "MenuAction/ClearFileAction.h" +#include "MenuAction/ClearPropertyAction.h" +#include "MenuAction/OpenFileAction.h" +#include "MenuAction/OpenDirAction.h" +#include "MenuAction/OpenWorkSpaceAction.h" +#include "MenuAction/ExitAction.h" +#include "MenuAction/GetPacsConfigDialogAction.h" + +#include "Model/FileModel.h" +#include "Model/PropertyTableModel.h" + +#include + +#include +#include +#include +#include +#include +#include + +DIDMainWindow::DIDMainWindow(QWidget *aParent) + : QMainWindow(aParent) + , mUI(new Ui::DIDMainWindow) + , mTreeView(new QTreeView(this)) + , mTableModel(new PropertyTableModel(this)) + , mTreeModel(new FileModel(mTableModel,this)) + , mTableView(new QTableView(this)) + +{ + mUI->setupUi(this); + initMenu(); + initFileWidget(); + initTable(); } -DIDMainWindow::~DIDMainWindow() { - +void DIDMainWindow::initTable() const { + QVBoxLayout* layout = new QVBoxLayout(mUI->mPropertyWidget); + layout->addWidget(mTableView); + mTableView->horizontalHeader()->setStretchLastSection(true); + mTableView->verticalHeader()->hide(); + mTableView->setModel(mTableModel); } + +DIDMainWindow::~DIDMainWindow() +{ + delete mUI; +} + +void DIDMainWindow::initMenu() +{ + QMenu* openMenu = new QMenu(tr("Open"),this); + auto fileAction = new OpenFileAction(tr("Open File"),this); + connect(fileAction, &OpenFileAction::dataLoaded,this, &DIDMainWindow::loadPropertyTable); + openMenu->addAction(fileAction); + auto dirAction = new OpenDirAction(tr("Open Directory"),this); + connect(dirAction, &OpenDirAction::dataLoaded,this, &DIDMainWindow::loadPropertyTable); + openMenu->addAction(dirAction); + openMenu->addAction(new OpenWorkSpaceAction(tr("Open WorkSpace"),this)); + openMenu->addSeparator(); + openMenu->addAction(new ExitAction(tr("Exit"),this)); + + QMenu* clearMenu = new QMenu(tr("Clear"),this); + clearMenu->addAction(new ClearFileAction(tr("Clear File"),mTreeModel,this)); + clearMenu->addAction(new ClearPropertyAction(tr("Clear Property"),mTableModel,this)); + + QMenu* pacsMenu = new QMenu(tr("PACS"),this); + pacsMenu->addAction(new GetPacsConfigDialogAction(tr("Config"),this)); + + mUI->mMenuBar->addMenu(openMenu); + mUI->mMenuBar->addMenu(clearMenu); + mUI->mMenuBar->addMenu(pacsMenu); +} + +void DIDMainWindow::initFileWidget() +{ + QVBoxLayout* layout = new QVBoxLayout(mUI->mFileWidget); + layout->addWidget(mTreeView); + + mTreeView->setModel(mTreeModel); + mTreeView->setHeaderHidden(true); + connect(mTreeView,&QAbstractItemView::doubleClicked,mTreeModel,&FileModel::executeItemAction); +} + +void DIDMainWindow::loadPropertyTable(bool loadSuccess) +{ + if (loadSuccess){ + mTreeModel->setModelData(); + } + else{ + QMessageBox::warning(this,"Warning","No DICOM loaded"); + } +} + diff --git a/DIDKit/App/DIDMainWindow.h b/DIDKit/App/DIDMainWindow.h index 913b655..041e276 100644 --- a/DIDKit/App/DIDMainWindow.h +++ b/DIDKit/App/DIDMainWindow.h @@ -1,20 +1,38 @@ -// -// Created by Krad on 2022/9/20. -// +#ifndef DIDMAINWINDOW_H +#define DIDMAINWINDOW_H -#ifndef OMEGAV_DIDMAINWINDOW_H -#define OMEGAV_DIDMAINWINDOW_H +#include -#include +namespace Ui { +class DIDMainWindow; +} -class DIDMainWindow : public QMainWindow{ - Q_OBJECT +class QTreeView; +class QTableView; +class FileModel; +class PropertyTableModel; - public: - explicit DIDMainWindow(QWidget *parent = Q_NULLPTR); - ~DIDMainWindow(); +class DIDMainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit DIDMainWindow(QWidget *aParent = nullptr); + ~DIDMainWindow(); + +private: + void initMenu(); + void initFileWidget(); + void loadPropertyTable(bool loadSuccess); + +private: + Ui::DIDMainWindow *mUI; + QTreeView* mTreeView; + PropertyTableModel* mTableModel; + FileModel* mTreeModel; + QTableView* mTableView; + + void initTable() const; }; - -#endif //OMEGAV_DIDMAINWINDOW_H +#endif // DIDMAINWINDOW_H diff --git a/DIDKit/App/DIDMainWindow.ui b/DIDKit/App/DIDMainWindow.ui new file mode 100644 index 0000000..548b8ef --- /dev/null +++ b/DIDKit/App/DIDMainWindow.ui @@ -0,0 +1,40 @@ + + + DIDMainWindow + + + + 0 + 0 + 670 + 469 + + + + DIDMainWindow + + + + + + + + + + + + + + + 0 + 0 + 670 + 23 + + + + + + + + diff --git a/DIDKit/App/MenuAction/ClearFileAction.cpp b/DIDKit/App/MenuAction/ClearFileAction.cpp new file mode 100644 index 0000000..f51f6f3 --- /dev/null +++ b/DIDKit/App/MenuAction/ClearFileAction.cpp @@ -0,0 +1,19 @@ +#include "ClearFileAction.h" +#include "Model/FileModel.h" + +ClearFileAction::ClearFileAction(const QString& aName, FileModel* aModel, QWidget* aParent) + : QAction(aName, aParent) + , mModel(aModel) +{ + connect(this,&QAction::triggered,this,&ClearFileAction::executeAction); +} + +ClearFileAction::~ClearFileAction() +{ + +} + +void ClearFileAction::executeAction() +{ + mModel->clearModelData(); +} diff --git a/DIDKit/App/MenuAction/ClearFileAction.h b/DIDKit/App/MenuAction/ClearFileAction.h new file mode 100644 index 0000000..874d776 --- /dev/null +++ b/DIDKit/App/MenuAction/ClearFileAction.h @@ -0,0 +1,21 @@ +#ifndef CLEARFILEACTION_H +#define CLEARFILEACTION_H + +#include + +class FileModel; + +class ClearFileAction : public QAction +{ +public: + ClearFileAction(const QString& aName,FileModel* aModel, QWidget* aParent = nullptr); + ~ClearFileAction() override; + +private: + void executeAction(); + +private: + FileModel* mModel; +}; + +#endif // CLEARFILEACTION_H diff --git a/DIDKit/App/MenuAction/ClearPropertyAction.cpp b/DIDKit/App/MenuAction/ClearPropertyAction.cpp new file mode 100644 index 0000000..395852c --- /dev/null +++ b/DIDKit/App/MenuAction/ClearPropertyAction.cpp @@ -0,0 +1,20 @@ +#include "ClearPropertyAction.h" + +#include "Model/PropertyTableModel.h" + +ClearPropertyAction::ClearPropertyAction(const QString& aName, PropertyTableModel* aModel, QWidget* aParent) + : QAction(aName, aParent) + , mModel(aModel) +{ + connect(this,&QAction::triggered,this,&ClearPropertyAction::executeAction); +} + +ClearPropertyAction::~ClearPropertyAction() +{ + +} + +void ClearPropertyAction::executeAction() +{ + mModel->removeRows(0,mModel->rowCount());; +} diff --git a/DIDKit/App/MenuAction/ClearPropertyAction.h b/DIDKit/App/MenuAction/ClearPropertyAction.h new file mode 100644 index 0000000..6fa0b71 --- /dev/null +++ b/DIDKit/App/MenuAction/ClearPropertyAction.h @@ -0,0 +1,21 @@ +#ifndef CLEARPROPERTYACTION_H +#define CLEARPROPERTYACTION_H + +#include + +class PropertyTableModel; + +class ClearPropertyAction : public QAction +{ +public: + ClearPropertyAction(const QString& aName,PropertyTableModel* aModel, QWidget* aParent = nullptr); + ~ClearPropertyAction() override; + +private: + void executeAction(); + +private: + PropertyTableModel* mModel; +}; + +#endif // CLEARPROPERTYACTION_H diff --git a/DIDKit/App/MenuAction/ExitAction.cpp b/DIDKit/App/MenuAction/ExitAction.cpp new file mode 100644 index 0000000..1e7a86b --- /dev/null +++ b/DIDKit/App/MenuAction/ExitAction.cpp @@ -0,0 +1,17 @@ +#include "ExitAction.h" + +ExitAction::ExitAction(const QString& aName,QWidget* aParent) + : QAction(aName, aParent) +{ + connect(this,&QAction::triggered,this,&ExitAction::executeAction); +} + +ExitAction::~ExitAction() +{ + +} + +void ExitAction::executeAction() +{ + exit(0); +} diff --git a/DIDKit/App/MenuAction/ExitAction.h b/DIDKit/App/MenuAction/ExitAction.h new file mode 100644 index 0000000..e861d9f --- /dev/null +++ b/DIDKit/App/MenuAction/ExitAction.h @@ -0,0 +1,16 @@ +#ifndef EXITACTION_H +#define EXITACTION_H + +#include + +class ExitAction : public QAction +{ +public: + ExitAction(const QString& aName, QWidget* aParent = nullptr); + ~ExitAction() override; + +private: + void executeAction(); +}; + +#endif // EXITACTION_H diff --git a/DIDKit/App/MenuAction/GetPacsConfigDialogAction.cpp b/DIDKit/App/MenuAction/GetPacsConfigDialogAction.cpp new file mode 100644 index 0000000..bdd6128 --- /dev/null +++ b/DIDKit/App/MenuAction/GetPacsConfigDialogAction.cpp @@ -0,0 +1,20 @@ +#include "GetPacsConfigDialogAction.h" + +#include "PACS/Widget/importwidget.h" + +GetPacsConfigDialogAction::GetPacsConfigDialogAction(const QString& aName,QWidget* aParent) + : QAction(aName, aParent) + , mWidget(new ImportWidget(aParent)) +{ + connect(this,&QAction::triggered,this,&GetPacsConfigDialogAction::executeAction); +} + +GetPacsConfigDialogAction::~GetPacsConfigDialogAction() +{ + +} + +void GetPacsConfigDialogAction::executeAction() +{ + mWidget->show(); +} diff --git a/DIDKit/App/MenuAction/GetPacsConfigDialogAction.h b/DIDKit/App/MenuAction/GetPacsConfigDialogAction.h new file mode 100644 index 0000000..65485fc --- /dev/null +++ b/DIDKit/App/MenuAction/GetPacsConfigDialogAction.h @@ -0,0 +1,21 @@ +#ifndef GETPACSCONFIGDIALOGACTION_H +#define GETPACSCONFIGDIALOGACTION_H + +#include + +class ImportWidget; + +class GetPacsConfigDialogAction : public QAction +{ +public: + GetPacsConfigDialogAction(const QString& aName, QWidget* aParent = nullptr); + ~GetPacsConfigDialogAction() override; + +private: + void executeAction(); + +private: + ImportWidget* mWidget; +}; + +#endif // GETPACSCONFIGDIALOGACTION_H diff --git a/DIDKit/App/MenuAction/OpenDirAction.cpp b/DIDKit/App/MenuAction/OpenDirAction.cpp new file mode 100644 index 0000000..e37d1db --- /dev/null +++ b/DIDKit/App/MenuAction/OpenDirAction.cpp @@ -0,0 +1,41 @@ +#include "OpenDirAction.h" + +#include +#include + +#include "IO/DICOM/DicomLoader.h" +#include "DICOMPropertiesStore.h" + +OpenDirAction::OpenDirAction(const QString& aName,QWidget* aParent) + : QAction(aName, aParent) +{ + connect(this,&QAction::triggered,this,&OpenDirAction::executeAction); +} + +OpenDirAction::~OpenDirAction() +{ + +} + +void OpenDirAction::executeAction() +{ + QString path = QFileDialog::getExistingDirectory(menu(), + tr("Open Directory"), QDir::currentPath(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + DicomLoader::InitCodecs(); + std::string dir = path.toStdString(); + std::vector vector; + int count = 0; + DicomLoader::readPropertiesFromDir(dir,vector, count); + DicomLoader::FinalizeCodecs(); + if( vector.empty()){ + emit dataLoaded(false); + return; + } + DICOMPropertiesStore::GetInstance()->reset(); + for (auto item : vector) { + DICOMPropertiesStore::GetInstance()->addProperty(item); + } + emit dataLoaded(true); +} + diff --git a/DIDKit/App/MenuAction/OpenDirAction.h b/DIDKit/App/MenuAction/OpenDirAction.h new file mode 100644 index 0000000..4a02f3a --- /dev/null +++ b/DIDKit/App/MenuAction/OpenDirAction.h @@ -0,0 +1,18 @@ +#ifndef OPENDIRACTION_H +#define OPENDIRACTION_H + +#include + +class OpenDirAction : public QAction +{ + Q_OBJECT +public: + OpenDirAction(const QString& aName, QWidget* aParent = nullptr); + ~OpenDirAction() override; + signals: + void dataLoaded(bool loadSuccess); +private: + void executeAction(); +}; + +#endif // OPENDIRACTION_H diff --git a/DIDKit/App/MenuAction/OpenFileAction.cpp b/DIDKit/App/MenuAction/OpenFileAction.cpp new file mode 100644 index 0000000..7417b66 --- /dev/null +++ b/DIDKit/App/MenuAction/OpenFileAction.cpp @@ -0,0 +1,41 @@ +#include "OpenFileAction.h" +#include + +#include +#include +#include + +#include "IO/DICOM/DicomLoader.h" +#include "DICOMPropertiesStore.h" + +OpenFileAction::OpenFileAction(const QString& aName,QWidget* aParent) + : QAction(aName, aParent) +{ + connect(this,&QAction::triggered,this,&OpenFileAction::executeAction); +} + + +OpenFileAction::~OpenFileAction() +{ + +} + +void OpenFileAction::executeAction() +{ + QString path = QFileDialog::getOpenFileName(menu());; + DicomLoader::InitCodecs(); + std::string file = path.toStdString(); + std::vector vector; + int count = 0; + DicomLoader::readPropertiesFromFile(file,vector, count); + DicomLoader::FinalizeCodecs(); + if( vector.empty()){ + emit dataLoaded(false); + return; + } + DICOMPropertiesStore::GetInstance()->reset(); + for (auto item : vector) { + DICOMPropertiesStore::GetInstance()->addProperty(item); + } + emit dataLoaded(true); +} diff --git a/DIDKit/App/MenuAction/OpenFileAction.h b/DIDKit/App/MenuAction/OpenFileAction.h new file mode 100644 index 0000000..fd912e7 --- /dev/null +++ b/DIDKit/App/MenuAction/OpenFileAction.h @@ -0,0 +1,18 @@ +#ifndef OPENFILEACTION_H +#define OPENFILEACTION_H + +#include + +class OpenFileAction : public QAction +{ + Q_OBJECT +public: + OpenFileAction(const QString& aName, QWidget* aParent = nullptr); + ~OpenFileAction() override; +signals: + void dataLoaded(bool loadSuccess); +private: + void executeAction(); +}; + +#endif // OPENFILEACTION_H diff --git a/DIDKit/App/MenuAction/OpenWorkSpaceAction.cpp b/DIDKit/App/MenuAction/OpenWorkSpaceAction.cpp new file mode 100644 index 0000000..91c97d7 --- /dev/null +++ b/DIDKit/App/MenuAction/OpenWorkSpaceAction.cpp @@ -0,0 +1,22 @@ +#include "OpenWorkSpaceAction.h" + +#include +#include +#include + +OpenWorkSpaceAction::OpenWorkSpaceAction(const QString& aName,QWidget* aParent) + : QAction(aName, aParent) +{ + connect(this,&QAction::triggered,this,&OpenWorkSpaceAction::executeAction); +} + + +OpenWorkSpaceAction::~OpenWorkSpaceAction() +{ + +} + +void OpenWorkSpaceAction::executeAction() +{ + +} diff --git a/DIDKit/App/MenuAction/OpenWorkSpaceAction.h b/DIDKit/App/MenuAction/OpenWorkSpaceAction.h new file mode 100644 index 0000000..2510786 --- /dev/null +++ b/DIDKit/App/MenuAction/OpenWorkSpaceAction.h @@ -0,0 +1,16 @@ +#ifndef OPENWORKSPACEACTION_H +#define OPENWORKSPACEACTION_H + +#include + +class OpenWorkSpaceAction : public QAction +{ +public: + OpenWorkSpaceAction(const QString& aName, QWidget* aParent = nullptr); + ~OpenWorkSpaceAction() override; + +private: + void executeAction(); +}; + +#endif // OPENWORKSPACEACTION_H diff --git a/DIDKit/App/Model/FileItem.cpp b/DIDKit/App/Model/FileItem.cpp new file mode 100644 index 0000000..8142137 --- /dev/null +++ b/DIDKit/App/Model/FileItem.cpp @@ -0,0 +1,82 @@ +#include "FileItem.h" +#include "FileItemAction.h" + +FileItem::FileItem(FileItemDataPointer mData, FileItem* aParent, FileItemActionPointer aAction) + : mParent(aParent) + , mChilds(QList()) + , mData(mData) + , mAction(aAction) +{ + if (mParent != nullptr) + { + mParent->setChild(this); + } +} + +FileItem::~FileItem() +{ + qDeleteAll(mChilds); + mChilds.clear(); +} + +void FileItem::setChild(FileItem* aChild) +{ + mChilds.append(aChild); +} + +void FileItem::setChilds(const QList& aChilds) +{ + mChilds.append(aChilds); +} + +void FileItem::removeChild(int aIndex) +{ + mChilds.removeAt(aIndex); +} + +int FileItem::childCount() +{ + return mChilds.count(); +} + +FileItem* FileItem::getChild(int aIndex) +{ + if (aIndex < mChilds.count()) + { + return mChilds.at(aIndex); + } + return nullptr; +} + +FileItem* FileItem::getParent() +{ + return mParent; +} + +FileItemDataPointer FileItem::getData() +{ + return mData; +} + +int FileItem::getIndexRow() +{ + if (mParent) + { + return mParent->mChilds.indexOf(this); + } + return 0; +} + +void FileItem::clearChilds() +{ + qDeleteAll(mChilds); + mChilds.clear(); +} + +void FileItem::executeAction() +{ + if(!mAction.isNull()) + { + mAction->execute(); + } +} diff --git a/DIDKit/App/Model/FileItem.h b/DIDKit/App/Model/FileItem.h new file mode 100644 index 0000000..f147da1 --- /dev/null +++ b/DIDKit/App/Model/FileItem.h @@ -0,0 +1,37 @@ +#ifndef FILEITEM_H +#define FILEITEM_H + +#include +#include +#include + +class FileItemAction; +typedef QSharedPointer FileItemDataPointer; +typedef QSharedPointer FileItemActionPointer; + + +class FileItem +{ +public: + explicit FileItem(FileItemDataPointer aData, FileItem* aParent = nullptr, FileItemActionPointer aAction = QSharedPointer()); + ~FileItem(); + void setChild(FileItem* aChild); + void setChilds(const QList& aChilds); + void removeChild(int aIndex); + int childCount(); + FileItem* getChild(int aIndex); + FileItem* getParent(); + FileItemDataPointer getData(); + int getIndexRow(); + void clearChilds(); + void executeAction(); + +private: + FileItem* mParent; + QList mChilds; + FileItemDataPointer mData; + FileItemActionPointer mAction; + +}; + +#endif // FILEITEM_H diff --git a/DIDKit/App/Model/FileItemAction.cpp b/DIDKit/App/Model/FileItemAction.cpp new file mode 100644 index 0000000..afcac4f --- /dev/null +++ b/DIDKit/App/Model/FileItemAction.cpp @@ -0,0 +1,24 @@ +#include "FileItemAction.h" + +#include "IO/DICOM/ExtendMedicalImageProperties.h" +#include "PropertyTableModel.h" + +FileItemAction::FileItemAction(PropertyTableModel* aTableModel, ExtendMedicalImageProperties* aProperty) + : mTableModel(aTableModel) + , mProperty(aProperty) +{ + +} + +void FileItemAction::execute() +{ + mTableModel->setModelData(0,0,mProperty->GetSeriesNumber()); + mTableModel->setModelData(0,1,mProperty->GetSeriesDescription()); + mTableModel->setModelData(0,2,mProperty->GetAcquisitionDate()); + mTableModel->setModelData(0,3,mProperty->GetAcquisitionTime()); + mTableModel->setModelData(0,4,mProperty->GetModality()); + mTableModel->setModelData(0,5,QString::number(mProperty->GetColumns())); + mTableModel->setModelData(0,6,QString::number(mProperty->GetRows())); + mTableModel->setModelData(0,7,QString::number(mProperty->GetFileNames().size())); + +} diff --git a/DIDKit/App/Model/FileItemAction.h b/DIDKit/App/Model/FileItemAction.h new file mode 100644 index 0000000..2df2b4c --- /dev/null +++ b/DIDKit/App/Model/FileItemAction.h @@ -0,0 +1,18 @@ +#ifndef FILEITEMACTION_H +#define FILEITEMACTION_H + +class ExtendMedicalImageProperties; +class PropertyTableModel; + +class FileItemAction +{ +public: + FileItemAction(PropertyTableModel* aTableModel, ExtendMedicalImageProperties* aProperty); + void execute(); + +private: + PropertyTableModel* mTableModel; + ExtendMedicalImageProperties* mProperty; +}; + +#endif // FILEITEMACTION_H diff --git a/DIDKit/App/Model/FileModel.cpp b/DIDKit/App/Model/FileModel.cpp new file mode 100644 index 0000000..cb0ec30 --- /dev/null +++ b/DIDKit/App/Model/FileModel.cpp @@ -0,0 +1,180 @@ +#include "FileModel.h" +#include "FileItem.h" +#include "FileItemAction.h" + +#include "IO/DICOM/ExtendMedicalImageProperties.h" +#include "DICOMPropertiesStore.h" + +FileModel::FileModel(PropertyTableModel* aTableModel, QObject *parent) + : QAbstractItemModel(parent) + , mRootItem(new FileItem(FileItemDataPointer(new QVariant("root")))) + , mPatientList(nullptr) + , mTableModel(aTableModel) +{ + setModelData(); +} + +FileModel::~FileModel() +{ + delete mRootItem; +} + +QVariant FileModel::data(const QModelIndex &aIndex, int aRole) const +{ + if (aRole != Qt::DisplayRole) + { + return QVariant(); + } + + if (!aIndex.isValid()) + { + return *mRootItem->getData(); + } + + FileItem* item = static_cast(aIndex.internalPointer()); + if (item == nullptr) + { + return QVariant(); + } + + return *item->getData(); +} + +QModelIndex FileModel::index(int aRow, int aColumn, const QModelIndex &aParent) const +{ + if (!hasIndex(aRow, aColumn, aParent)) + { + return QModelIndex(); + } + + FileItem* parentItem; + + if (!aParent.isValid()) + { + parentItem = mRootItem; + } + else + { + parentItem = static_cast(aParent.internalPointer()); + } + + FileItem* childItem = parentItem->getChild(aRow); + if (childItem) + { + return createIndex(aRow, aColumn, childItem); + } + else + { + return QModelIndex(); + } +} + +QModelIndex FileModel::parent(const QModelIndex &aIndex) const +{ + if (!aIndex.isValid()) + { + return QModelIndex(); + } + + FileItem *childItem = static_cast(aIndex.internalPointer()); + FileItem *parentItem = childItem->getParent(); + + if (parentItem == nullptr || parentItem == mRootItem) + { + return QModelIndex(); + } + + return createIndex(parentItem->getIndexRow(), 0, parentItem); +} + +int FileModel::rowCount(const QModelIndex& aParent) const +{ + if (aParent.column() > 0) + { + return 0; + } + + if (!aParent.isValid()) + { + return mRootItem->childCount(); + } + + FileItem* item = static_cast(aParent.internalPointer()); + if(item == nullptr) + { + return 0; + } + return item->childCount(); +} + +int FileModel::columnCount(const QModelIndex &aParent) const +{ + return 1; +} + +void FileModel::setModelData() +{ + clearModelData(); + mPatientList = DICOMPropertiesStore::GetInstance()->getPatientsList(); + beginResetModel(); + //Patient Node + std::map::iterator patientIter; + for(patientIter = mPatientList->begin();patientIter != mPatientList->end(); ++patientIter) + { + FileItem* patient = new FileItem( + FileItemDataPointer(new QVariant(QString("Patient: %1, Name: %2, Birth Date: %3") + .arg(patientIter->first.c_str(),patientIter->second->patient_name.c_str(),patientIter->second->birth_date.c_str()))),mRootItem); + //Study Node + std::map::iterator studyIter; + StudiesMapType* studyMap = patientIter->second->studies; + for(studyIter = studyMap->begin();studyIter != studyMap->end(); ++studyIter) + { + FileItem* study = new FileItem(FileItemDataPointer(new QVariant(QString("Study: %1, Date: %2") + .arg(studyIter->first.c_str(), studyIter->second->study_date.c_str()))),patient); + //Series Node + std::map::iterator seriesIter; + SeriesMapType* seriesMap = studyIter->second->series; + for(seriesIter = seriesMap->begin();seriesIter != seriesMap->end(); ++seriesIter) + { + FileItem* series = new FileItem(FileItemDataPointer(new QVariant(QString("Series: ")+seriesIter->first.c_str())),study); + //Image Set Node + std::map::iterator imageSetIter; + ImageSetMapType* imageSetMap = seriesIter->second; + for(imageSetIter = imageSetMap->begin();imageSetIter != imageSetMap->end(); ++imageSetIter) + { + ExtendMedicalImageProperties* property = imageSetIter->second; + FileItem* imageSet = new FileItem(FileItemDataPointer(new QVariant(QString("ImageSet: ")+imageSetIter->first.c_str() + QString(" ") + + QString::number(property->GetFileNames().size()))) + , series + , FileItemActionPointer(new FileItemAction(mTableModel,property))); + + } + } + } + } + endResetModel(); +} + +void FileModel::clearModelData() +{ + if (rowCount() == 0) + { + return; + } + beginResetModel(); + mRootItem->clearChilds(); + endResetModel(); +} + +void FileModel::executeItemAction(const QModelIndex& aIndex) +{ + if(aIndex.isValid()) + { + FileItem* item = static_cast(aIndex.internalPointer()); + if (item != nullptr) + { + item->executeAction(); + } + } +} + diff --git a/DIDKit/App/Model/FileModel.h b/DIDKit/App/Model/FileModel.h new file mode 100644 index 0000000..737b166 --- /dev/null +++ b/DIDKit/App/Model/FileModel.h @@ -0,0 +1,35 @@ +#ifndef FILEMODEL_H +#define FILEMODEL_H + +#include + +#include "IO/Common/DICOMTypes.h" + +class FileItem; +class PropertyTableModel; + +class FileModel : public QAbstractItemModel +{ +public: + explicit FileModel(PropertyTableModel* aTableModel, QObject *parent = nullptr); + ~FileModel() override; + + QVariant data(const QModelIndex &aIndex, int aRole) const override; +// Qt::ItemFlags flags(const QModelIndex &aIndex) const override; +// QVariant headerData(int aSection, Qt::Orientation orientation, +// int aRole = Qt::DisplayRole) const override; + QModelIndex index(int aRow, int aColumn, const QModelIndex &aParent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &aIndex) const override; + int rowCount(const QModelIndex &aParent = QModelIndex()) const override; + int columnCount(const QModelIndex &aParent = QModelIndex()) const override; + void setModelData(); + void clearModelData(); + void executeItemAction(const QModelIndex& aIndex); + +private: + FileItem* mRootItem; + PatientsMapType* mPatientList; + PropertyTableModel* mTableModel; +}; + +#endif // FILEMODEL_H diff --git a/DIDKit/App/Model/PropertyTableModel.cpp b/DIDKit/App/Model/PropertyTableModel.cpp new file mode 100644 index 0000000..17a38e6 --- /dev/null +++ b/DIDKit/App/Model/PropertyTableModel.cpp @@ -0,0 +1,22 @@ +#include "PropertyTableModel.h" +#include +#include + +PropertyTableModel::PropertyTableModel(QObject *parent) + : QStandardItemModel(parent) +{ + setHorizontalHeaderLabels(QStringList()< + +class PropertyTableModel : public QStandardItemModel +{ +public: + explicit PropertyTableModel(QObject *parent = nullptr); + ~PropertyTableModel() override; + void setModelData(int aRow,int aColumn,const QString& aData); + +}; + +#endif // PROPERTYTABLEMODEL_H diff --git a/DIDKit/App/app.cpp b/DIDKit/App/app.cpp index 7adb77c..5d1ad27 100644 --- a/DIDKit/App/app.cpp +++ b/DIDKit/App/app.cpp @@ -9,42 +9,20 @@ #include "IO/Convert/DICOMToPNGConverter.h" #include "IO/Convert/DICOMToJPEGConverter.h" -#include "IO/DICOM/MultiframeDICOMSpliter.h" - #include "DIDMainWindow.h" -int main(int argc, char* argv[]) { - MultiframeDICOMSpliter spliter; - spliter.SetInputFileName("F:\\Special DICOM\\112255\\b65b0956-c046-11ea-a50f-509a4c8d26e3_08870001_37445_112255_7328989.dcm"); - spliter.SetOutputDirPath("D:\\mounttest"); - spliter.SetOutputFilePattern("%d.dcm"); - spliter.write(); - return 0; - DICOMToBMPConverter converter; - converter.setOutputSize(300, 300); - converter.setFrame(2); - converter.setInputDICOMFile("F:\\Kinds Data Files\\MultiFrame\\MultiFrame_Anon.dcm"); +int main(int argc, char* argv[]) +{ + QTextCodec* codec = QTextCodec::codecForName("GB2312"); + QTextCodec::setCodecForLocale(codec); - converter.save("D:\\test.bmp"); - DICOMToPNGConverter pconverter; - pconverter.setFrame(2); - pconverter.setOutputSize(300, 300); - pconverter.setInputDICOMFile("D:\\TestData\\CT\\4905\\a8c5c508-06b8-11ea-9b1e-509a4c8d26e3_08870001_4905_10903_287571"); - pconverter.save("D:\\test.png"); - DICOMToJPEGConverter jconverter; - jconverter.setOutputSize(300, 300); - jconverter.setInputDICOMFile("D:\\TestData\\CT\\4905\\a8c5c508-06b8-11ea-9b1e-509a4c8d26e3_08870001_4905_10903_287571"); - jconverter.save("D:\\test.jpg"); -// QTextCodec* codec = QTextCodec::codecForName("GB2312"); -// QTextCodec::setCodecForLocale(codec); -// -// QApplication a(argc, argv); -// -// QFont font; -// font.setFamily(QString::fromUtf8("Arial")); -// QApplication::setFont(font); -// -// DIDMainWindow w; -// w.show(); -// return a.exec(); + QApplication a(argc, argv); + + QFont font; + font.setFamily(QString::fromUtf8("Arial")); + QApplication::setFont(font); + + DIDMainWindow w; + w.show(); + return a.exec(); } diff --git a/DIDKit/CMakeLists.txt b/DIDKit/CMakeLists.txt index 95a019e..5e63af4 100644 --- a/DIDKit/CMakeLists.txt +++ b/DIDKit/CMakeLists.txt @@ -4,13 +4,14 @@ file(GLOB_RECURSE DIDKit_IO_headers ../src/src/IO/*.h) file(GLOB_RECURSE DIDKit_IO_cpps ../src/src/IO/*.cpp) file(GLOB_RECURSE DIDKit_PACS_headers ../src/src/PACS/*.h) file(GLOB_RECURSE DIDKit_PACS_cpps ../src/src/PACS/*.cpp) -file(GLOB_RECURSE DIDKit_App_headers App/*.h) -file(GLOB_RECURSE DIDKit_App_cpps App/*.cpp) +file(GLOB_RECURSE DIDKit_App_headers ./*/*.h) +file(GLOB_RECURSE DIDKit_App_cpps ./*/*.cpp) set(BUILD_SHARED_LIBS ON) if (${BUILD_SHARED_LIBS}) include_directories(Defines/) endif() include_directories(../src/src/) +include_directories(./App/) add_library(DIDKit SHARED ${DIDKit_headers} ${DIDKit_cpps}) @@ -20,7 +21,6 @@ set(BUILD_DIDKit_APP ON) find_package(DCMTK REQUIRED) include_directories(${DCMTK_INCLUDE_DIRS}) - include_directories(${DCM_NETWORK_INCLUDE_DIRS}) find_package(VTK REQUIRED) @@ -33,12 +33,14 @@ target_link_libraries(DIDKit ${VTK_LIBRARIES}) target_link_libraries(DIDKit dcm_network) add_dependencies(DIDKit dcm_network) +file(GLOB_RECURSE DIDKit_UI ./*/*.ui) +qt5_wrap_ui(DIDKit_UI_FILES ${DIDKit_UI}) + if(${BUILD_DIDKit_APP}) - add_executable(DIDKitApp ${DIDKit_IO_headers} ${DIDKit_IO_cpps} ${DIDKit_App_headers} ${DIDKit_App_cpps} - ${DIDKit_PACS_headers} ${DIDKit_PACS_cpps}) + add_executable(DIDKitApp ${DIDKit_IO_headers} ${DIDKit_IO_cpps} ${DIDKit_App_headers} ${DIDKit_App_cpps} ${DIDKit_PACS_headers} ${DIDKit_PACS_cpps} ${DIDKit_UI_FILES}) target_link_libraries(DIDKitApp ${DCMTK_LIBRARIES}) target_link_libraries(DIDKitApp ${VTK_LIBRARIES}) target_link_libraries(DIDKitApp dcm_network) add_dependencies(DIDKitApp dcm_network) target_link_libraries(DIDKitApp Qt5::Core Qt5::Widgets Qt5::Gui) -endif() \ No newline at end of file +endif() diff --git a/src/src/Common/ImageSetStore.cpp b/src/src/Common/ImageSetStore.cpp index a05554f..ecc3c24 100644 --- a/src/src/Common/ImageSetStore.cpp +++ b/src/src/Common/ImageSetStore.cpp @@ -82,11 +82,13 @@ void ImageSetStore::addImageSet(ExtendMedicalImageProperties* property) { if (study->series->count(series_uid)>0){ study->series->at(series_uid)->insert({property->GetUniqueID(),property}); imageProperties.push_back(property); + property->Register(placeHolder); } else { ImageSetMapType* v = new ImageSetMapType; v->insert({property->GetUniqueID(),property}); study->series->insert({series_uid,v}); imageProperties.push_back(property); + property->Register(placeHolder); } } diff --git a/src/src/IO/DICOM/ExtendMedicalImageProperties.cpp b/src/src/IO/DICOM/ExtendMedicalImageProperties.cpp index 38b69b8..693024f 100644 --- a/src/src/IO/DICOM/ExtendMedicalImageProperties.cpp +++ b/src/src/IO/DICOM/ExtendMedicalImageProperties.cpp @@ -86,14 +86,10 @@ bool ExtendMedicalImageProperties::RescaledImageDataIsSigned() void ExtendMedicalImageProperties::GenerateUniqueID() { std::string uniqueID; - uniqueID.append(PatientName); - uniqueID.append("_"); - uniqueID.append(StudyUID); - uniqueID.append("_"); uniqueID.append(SeriesUID); uniqueID.append("_"); char img[200]={0}; - sprintf(img,"%ld", ImageSetNumber); + sprintf(img,"_%ld", ImageSetNumber); uniqueID.append(img); this->SetUniqueID(uniqueID.c_str()); }