From c2dcec961ff5f58ac8ee3ff0720b90de48aae77c Mon Sep 17 00:00:00 2001 From: Davide Punzo Date: Wed, 18 Oct 2023 09:22:19 +0200 Subject: [PATCH] ENH: Add results checks to the visual dicom browser --- Libs/DICOM/Core/ctkDICOMDatabase.cpp | 115 ++++++++++++------ Libs/DICOM/Core/ctkDICOMQuery.cpp | 23 ++-- Libs/DICOM/Core/ctkDICOMQuery.h | 13 +- Libs/DICOM/Core/ctkDICOMQueryTask.cpp | 11 +- Libs/DICOM/Core/ctkDICOMRetrieve.cpp | 113 ++++++++++++----- Libs/DICOM/Core/ctkDICOMRetrieve.h | 21 +++- Libs/DICOM/Core/ctkDICOMRetrieveTask.cpp | 33 ++++- Libs/DICOM/Core/ctkDICOMRetrieveTask.h | 4 + Libs/DICOM/Core/ctkDICOMRetrieveTask_p.h | 1 + Libs/DICOM/Core/ctkDICOMServer.cpp | 2 +- Libs/DICOM/Core/ctkDICOMServer.h | 2 +- Libs/DICOM/Core/ctkDICOMTaskPool.cpp | 39 +++--- Libs/DICOM/Core/ctkDICOMTaskPool.h | 16 ++- .../Widgets/Resources/UI/Icons/query.svg | 2 +- .../Widgets/Resources/UI/Icons/restore.svg | 1 - .../DICOM/Widgets/Resources/UI/Icons/wait.svg | 2 +- .../Widgets/Resources/UI/ctkDICOMWidget.qrc | 3 +- .../Widgets/ctkDICOMSeriesItemWidget.cpp | 14 ++- .../Widgets/ctkDICOMServerNodeWidget2.cpp | 12 +- .../Widgets/ctkDICOMVisualBrowserWidget.cpp | 35 +++++- .../Widgets/ctkDICOMVisualBrowserWidget.h | 1 + 21 files changed, 314 insertions(+), 149 deletions(-) delete mode 100644 Libs/DICOM/Widgets/Resources/UI/Icons/restore.svg diff --git a/Libs/DICOM/Core/ctkDICOMDatabase.cpp b/Libs/DICOM/Core/ctkDICOMDatabase.cpp index 3c5883c323..47a982dc5d 100644 --- a/Libs/DICOM/Core/ctkDICOMDatabase.cpp +++ b/Libs/DICOM/Core/ctkDICOMDatabase.cpp @@ -314,13 +314,10 @@ bool ctkDICOMDatabasePrivate::insertPatient(const ctkDICOMItem& dataset, int& db // Check if patient is already present in the db - QString patientsName, patientID, studyInstanceUID, seriesInstanceUID; - if (!this->uidsForDataSet(dataset, patientsName, patientID, studyInstanceUID, seriesInstanceUID)) - { - // error occurred, message is already logged - return false; - } - QString patientsBirthDate(dataset.GetElementAsString(DCM_PatientBirthDate)); + QString patientsName, patientID, patientsBirthDate; + patientsName = dataset.GetElementAsString(DCM_PatientName); + patientID = dataset.GetElementAsString(DCM_PatientID); + patientsBirthDate = dataset.GetElementAsString(DCM_PatientBirthDate); QSqlQuery checkPatientExistsQuery(this->Database); checkPatientExistsQuery.prepare("SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?"); @@ -968,10 +965,6 @@ void ctkDICOMDatabase::insert(QList taskResultsList) bool storeFile = taskResults->copyFile(); QMap datasets = taskResults->datasets(); - QString patientsUID = this->patientForStudy(taskResults->studyInstanceUID()); - QString patientID = taskResults->patientID(); - QString patientName = this->fieldForPatient("PatientsName", patientsUID); - for(QString key : datasets.keys()) { ctkDICOMItem* dataset = datasets.value(key); @@ -979,12 +972,82 @@ void ctkDICOMDatabase::insert(QList taskResultsList) { continue; } + QString patientID, patientName, studyInstanceUID, seriesInstanceUID;; + patientName = dataset->GetElementAsString(DCM_PatientName); + patientID = dataset->GetElementAsString(DCM_PatientID); + studyInstanceUID = dataset->GetElementAsString(DCM_StudyInstanceUID); + seriesInstanceUID = dataset->GetElementAsString(DCM_SeriesInstanceUID); + + if (patientID.isEmpty()) + { + if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryPatients) + { + patientID = key; + } + else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryStudies || + typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries || + typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveStudy || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance) + { + patientID = taskResults->patientID(); + } + + dataset->SetElementAsString(DCM_PatientID, patientID); + } + + if (studyInstanceUID.isEmpty()) + { + if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryStudies) + { + studyInstanceUID = key; + } + else if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries || + typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveStudy || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance) + { + studyInstanceUID = taskResults->studyInstanceUID(); + } + + dataset->SetElementAsString(DCM_StudyInstanceUID, studyInstanceUID); + } + + if (seriesInstanceUID.isEmpty()) + { + if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries) + { + seriesInstanceUID = key; + } + else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries || + typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance) + { + seriesInstanceUID = taskResults->seriesInstanceUID(); + } + + dataset->SetElementAsString(DCM_SeriesInstanceUID, seriesInstanceUID); + } + + if (patientID.isEmpty()) + { + logger.error("ctkDICOMDatabase::insert: dataset has no patientID"); + continue; + } + + if (patientName.isEmpty() && !patientID.isEmpty()) + { + patientName = patientID; + dataset->SetElementAsString(DCM_PatientName, patientName); + } if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances) { filePath = "server://" + taskResults->connectionName() + - "_" + taskResults->studyInstanceUID() + - "_" + taskResults->seriesInstanceUID() + + "_" + studyInstanceUID + + "_" + seriesInstanceUID + "_" + key; } @@ -1024,26 +1087,6 @@ void ctkDICOMDatabase::insert(QList taskResultsList) } } - if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries) - { - dataset->SetElementAsString(DCM_PatientName, patientName); - dataset->SetElementAsString(DCM_PatientID, patientID); - } - else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances) - { - dataset->SetElementAsString(DCM_PatientName, patientName); - dataset->SetElementAsString(DCM_PatientID, patientID); - dataset->SetElementAsString(DCM_StudyInstanceUID, taskResults->studyInstanceUID()); - } - - // Verify that minimum required fields are present - QString patientsName, studyInstanceUID, seriesInstanceUID; - if (!d->uidsForDataSet(*dataset, patientsName, patientID, studyInstanceUID, seriesInstanceUID)) - { - logger.error("Failed to insert dataset into database (required fields missing)"); - continue; - } - if (filePath.contains("server://") && storeFile) { filePath = ""; @@ -1059,7 +1102,7 @@ void ctkDICOMDatabase::insert(QList taskResultsList) } } - if (d->insertPatientStudySeries(*dataset, patientID, patientsName)) + if (d->insertPatientStudySeries(*dataset, patientID, patientName)) { databaseWasChanged = true; } @@ -1125,10 +1168,6 @@ void ctkDICOMDatabase::insert(QList taskResultsList) } } } - - patientsUID = this->patientForStudy(taskResults->studyInstanceUID()); - patientID = taskResults->patientID(); - patientName = this->fieldForPatient("PatientsName", patientsUID); } d->Database.commit(); diff --git a/Libs/DICOM/Core/ctkDICOMQuery.cpp b/Libs/DICOM/Core/ctkDICOMQuery.cpp index 67fa50494b..9f6083a781 100644 --- a/Libs/DICOM/Core/ctkDICOMQuery.cpp +++ b/Libs/DICOM/Core/ctkDICOMQuery.cpp @@ -118,8 +118,8 @@ ctkDICOMQueryPrivate::ctkDICOMQueryPrivate() this->Canceled = false; this->MaximumPatientsQuery = 2; - this->SCU.setACSETimeout(3); - this->SCU.setConnectionTimeout(3); + this->SCU.setACSETimeout(10); + this->SCU.setConnectionTimeout(10); } //------------------------------------------------------------------------------ @@ -601,7 +601,7 @@ bool ctkDICOMQuery::query(ctkDICOMDatabase& database) } //---------------------------------------------------------------------------- -bool ctkDICOMQuery::queryPatients(const QString &taskUID) +bool ctkDICOMQuery::queryPatients() { Q_D(ctkDICOMQuery); // In the following, we emit progress(int) after progress(QString), this @@ -678,7 +678,7 @@ bool ctkDICOMQuery::queryPatients(const QString &taskUID) ctkDICOMTaskResults* taskResults = new ctkDICOMTaskResults; taskResults->setTypeOfTask(ctkDICOMTaskResults::TaskType::QueryPatients); taskResults->setConnectionName(d->ConnectionName); - taskResults->setTaskUID(taskUID); + taskResults->setTaskUID(d->TaskUID); QMap datasetsMap; OFList responses; @@ -728,8 +728,7 @@ bool ctkDICOMQuery::queryPatients(const QString &taskUID) } //---------------------------------------------------------------------------- -bool ctkDICOMQuery::queryStudies(const QString& taskUID, - const QString& patientID) +bool ctkDICOMQuery::queryStudies(const QString& patientID) { Q_D(ctkDICOMQuery); // In the following, we emit progress(int) after progress(QString), this @@ -809,7 +808,7 @@ bool ctkDICOMQuery::queryStudies(const QString& taskUID, taskResults->setTypeOfTask(ctkDICOMTaskResults::TaskType::QueryStudies); taskResults->setPatientID(patientID.toStdString().c_str()); taskResults->setConnectionName(d->ConnectionName); - taskResults->setTaskUID(taskUID); + taskResults->setTaskUID(d->TaskUID); QMap datasetsMap; @@ -851,8 +850,7 @@ bool ctkDICOMQuery::queryStudies(const QString& taskUID, } //---------------------------------------------------------------------------- -bool ctkDICOMQuery::querySeries(const QString& taskUID, - const QString& patientID, +bool ctkDICOMQuery::querySeries(const QString& patientID, const QString& studyInstanceUID) { Q_D(ctkDICOMQuery); @@ -931,7 +929,7 @@ bool ctkDICOMQuery::querySeries(const QString& taskUID, taskResults->setPatientID(patientID.toStdString().c_str()); taskResults->setStudyInstanceUID(studyInstanceUID.toStdString().c_str()); taskResults->setConnectionName(d->ConnectionName); - taskResults->setTaskUID(taskUID); + taskResults->setTaskUID(d->TaskUID); QMap datasetsMap; @@ -973,8 +971,7 @@ bool ctkDICOMQuery::querySeries(const QString& taskUID, } //---------------------------------------------------------------------------- -bool ctkDICOMQuery::queryInstances(const QString& taskUID, - const QString& patientID, +bool ctkDICOMQuery::queryInstances(const QString& patientID, const QString& studyInstanceUID, const QString& seriesInstanceUID) { @@ -1052,7 +1049,7 @@ bool ctkDICOMQuery::queryInstances(const QString& taskUID, taskResults->setStudyInstanceUID(studyInstanceUID.toStdString().c_str()); taskResults->setSeriesInstanceUID(seriesInstanceUID.toStdString().c_str()); taskResults->setConnectionName(d->ConnectionName); - taskResults->setTaskUID(taskUID); + taskResults->setTaskUID(d->TaskUID); QMap datasetsMap; diff --git a/Libs/DICOM/Core/ctkDICOMQuery.h b/Libs/DICOM/Core/ctkDICOMQuery.h index 207e97ac7e..b346b2b5c3 100644 --- a/Libs/DICOM/Core/ctkDICOMQuery.h +++ b/Libs/DICOM/Core/ctkDICOMQuery.h @@ -72,7 +72,7 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMQuery : public QObject /// 0 by default. void setPort(int port); int port() const; - /// connection timeout, default 3 sec. + /// connection timeout, default 10 sec. void setConnectionTimeout(const int timeout); int connectionTimeout() const; /// maximum number of responses allowed in one query @@ -93,25 +93,22 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMQuery : public QObject /// Utility method to query a remote DICOM Image Store SCP only at patient level. /// You must at least set the host and port before calling query() - Q_INVOKABLE bool queryPatients(const QString& taskUID); + Q_INVOKABLE bool queryPatients(); /// Utility method to query a remote DICOM Image Store SCP only at study level. /// You must at least set the host and port before calling query() - Q_INVOKABLE bool queryStudies(const QString& taskUID, - const QString& patientID); + Q_INVOKABLE bool queryStudies(const QString& patientID); /// Utility method to query a remote DICOM Image Store SCP only at series level /// given a studyInstanceUID. /// You must at least set the host and port before calling query() - Q_INVOKABLE bool querySeries(const QString& taskUID, - const QString& patientID, + Q_INVOKABLE bool querySeries(const QString& patientID, const QString& studyInstanceUID); /// Utility method to query a remote DICOM Image Store SCP only at instance level /// given a studyInstanceUID and seriesInstanceUID. /// You must at least set the host and port before calling query() - Q_INVOKABLE bool queryInstances(const QString& taskUID, - const QString& patientID, + Q_INVOKABLE bool queryInstances(const QString& patientID, const QString& studyInstanceUID, const QString& seriesInstanceUID); diff --git a/Libs/DICOM/Core/ctkDICOMQueryTask.cpp b/Libs/DICOM/Core/ctkDICOMQueryTask.cpp index a1c1d3f0d5..9067f4010f 100644 --- a/Libs/DICOM/Core/ctkDICOMQueryTask.cpp +++ b/Libs/DICOM/Core/ctkDICOMQueryTask.cpp @@ -127,7 +127,7 @@ void ctkDICOMQueryTask::run() switch(d->QueryLevel) { case DICOMLevel::Patients: - if (!d->Query->queryPatients(this->taskUID())) + if (!d->Query->queryPatients()) { this->setIsFinished(true); emit canceled(); @@ -135,8 +135,7 @@ void ctkDICOMQueryTask::run() } break; case DICOMLevel::Studies: - if (!d->Query->queryStudies(this->taskUID(), - d->PatientID)) + if (!d->Query->queryStudies(d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -144,8 +143,7 @@ void ctkDICOMQueryTask::run() } break; case DICOMLevel::Series: - if (!d->Query->querySeries(this->taskUID(), - d->PatientID, + if (!d->Query->querySeries(d->PatientID, d->StudyInstanceUID)) { this->setIsFinished(true); @@ -154,8 +152,7 @@ void ctkDICOMQueryTask::run() } break; case DICOMLevel::Instances: - if (!d->Query->queryInstances(this->taskUID(), - d->PatientID, + if (!d->Query->queryInstances(d->PatientID, d->StudyInstanceUID, d->SeriesInstanceUID)) { diff --git a/Libs/DICOM/Core/ctkDICOMRetrieve.cpp b/Libs/DICOM/Core/ctkDICOMRetrieve.cpp index 51fefcc4c7..94bc5358f6 100644 --- a/Libs/DICOM/Core/ctkDICOMRetrieve.cpp +++ b/Libs/DICOM/Core/ctkDICOMRetrieve.cpp @@ -111,6 +111,7 @@ class ctkDICOMRetrieveSCUPrivate : public DcmSCU { taskResults->setTypeOfTask(ctkDICOMTaskResults::TaskType::RetrieveStudy); } + taskResults->setPatientID(this->retrieve->patientID()); taskResults->setStudyInstanceUID(this->retrieve->studyInstanceUID()); taskResults->setSeriesInstanceUID(this->retrieve->seriesInstanceUID()); taskResults->setSOPInstanceUID(qInstanceUID); @@ -175,6 +176,7 @@ class ctkDICOMRetrievePrivate: public QObject bool ConnectionParamsChanged; ctkDICOMRetrieve::RetrieveType LastRetrieveType; + QString PatientID; QString StudyInstanceUID; QString SeriesInstanceUID; QString ConnectionName; @@ -186,16 +188,19 @@ class ctkDICOMRetrievePrivate: public QObject QString MoveDestinationAETitle; QList TaskResultsList; - bool initializeSCU(const QString& studyInstanceUID, + bool initializeSCU(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType, DcmDataset *retrieveParameters); - bool move(const QString& studyInstanceUID, + bool move(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType); - bool get(const QString& studyInstanceUID, + bool get(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType); @@ -214,6 +219,7 @@ ctkDICOMRetrievePrivate::ctkDICOMRetrievePrivate(ctkDICOMRetrieve& obj) this->ConnectionParamsChanged = false; this->LastRetrieveType = ctkDICOMRetrieve::RetrieveNone; + this->PatientID = ""; this->StudyInstanceUID = ""; this->SeriesInstanceUID = ""; this->ConnectionName = ""; @@ -264,7 +270,8 @@ ctkDICOMRetrievePrivate::~ctkDICOMRetrievePrivate() } //------------------------------------------------------------------------------ -bool ctkDICOMRetrievePrivate::initializeSCU(const QString& studyInstanceUID, +bool ctkDICOMRetrievePrivate::initializeSCU(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType, @@ -307,6 +314,11 @@ bool ctkDICOMRetrievePrivate::initializeSCU(const QString& studyInstanceUID, // Always required to send all highler level unique keys, so add study here (we are in Study Root) retrieveParameters->putAndInsertString(DCM_StudyInstanceUID, studyInstanceUID.toStdString().c_str()); + if (!patientID.isEmpty()) + { + retrieveParameters->putAndInsertString(DCM_PatientID, + patientID.toStdString().c_str()); + } } else if (retrieveType == ctkDICOMRetrieve::RetrieveSeries) { @@ -316,12 +328,22 @@ bool ctkDICOMRetrievePrivate::initializeSCU(const QString& studyInstanceUID, // Always required to send all highler level unique keys, so add study here (we are in Study Root) retrieveParameters->putAndInsertString(DCM_StudyInstanceUID, studyInstanceUID.toStdString().c_str()); + if (!patientID.isEmpty()) + { + retrieveParameters->putAndInsertString(DCM_PatientID, + patientID.toStdString().c_str()); + } } else { retrieveParameters->putAndInsertString(DCM_QueryRetrieveLevel, "STUDY" ); retrieveParameters->putAndInsertString(DCM_StudyInstanceUID, studyInstanceUID.toStdString().c_str()); + if (!patientID.isEmpty()) + { + retrieveParameters->putAndInsertString(DCM_PatientID, + patientID.toStdString().c_str()); + } } this->LastRetrieveType = retrieveType; @@ -329,7 +351,8 @@ bool ctkDICOMRetrievePrivate::initializeSCU(const QString& studyInstanceUID, } //------------------------------------------------------------------------------ -bool ctkDICOMRetrievePrivate::move(const QString& studyInstanceUID, +bool ctkDICOMRetrievePrivate::move(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType) @@ -337,6 +360,7 @@ bool ctkDICOMRetrievePrivate::move(const QString& studyInstanceUID, Q_Q(ctkDICOMRetrieve); this->TaskResultsList.clear(); + this->PatientID = patientID; this->StudyInstanceUID = studyInstanceUID; this->SeriesInstanceUID = seriesInstanceUID; @@ -346,9 +370,15 @@ bool ctkDICOMRetrievePrivate::move(const QString& studyInstanceUID, } DcmDataset *retrieveParameters = new DcmDataset(); - if (!this->initializeSCU(studyInstanceUID, seriesInstanceUID, SOPInstanceUID, retrieveType, retrieveParameters)) + if (!this->initializeSCU(patientID, + studyInstanceUID, + seriesInstanceUID, + SOPInstanceUID, + retrieveType, + retrieveParameters)) { delete retrieveParameters; + logger.error("MOVE Request failed: SCU initialization failed"); return false; } @@ -486,7 +516,8 @@ bool ctkDICOMRetrievePrivate::move(const QString& studyInstanceUID, } //------------------------------------------------------------------------------ -bool ctkDICOMRetrievePrivate::get(const QString& studyInstanceUID, +bool ctkDICOMRetrievePrivate::get(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& SOPInstanceUID, const ctkDICOMRetrieve::RetrieveType retrieveType) @@ -494,6 +525,7 @@ bool ctkDICOMRetrievePrivate::get(const QString& studyInstanceUID, Q_Q(ctkDICOMRetrieve); this->TaskResultsList.clear(); + this->PatientID = patientID; this->StudyInstanceUID = studyInstanceUID; this->SeriesInstanceUID = seriesInstanceUID; @@ -503,9 +535,15 @@ bool ctkDICOMRetrievePrivate::get(const QString& studyInstanceUID, } DcmDataset *retrieveParameters = new DcmDataset(); - if (!this->initializeSCU(studyInstanceUID, seriesInstanceUID, SOPInstanceUID, retrieveType, retrieveParameters)) + if (!this->initializeSCU(patientID, + studyInstanceUID, + seriesInstanceUID, + SOPInstanceUID, + retrieveType, + retrieveParameters)) { delete retrieveParameters; + logger.error("MOVE Request failed: SCU initialization failed"); return false; } @@ -870,6 +908,13 @@ QString ctkDICOMRetrieve::taskUID() const return d->TaskUID; } +//------------------------------------------------------------------------------ +QString ctkDICOMRetrieve::patientID() const +{ + Q_D(const ctkDICOMRetrieve); + return d->PatientID; +} + //------------------------------------------------------------------------------ QString ctkDICOMRetrieve::studyInstanceUID() const { @@ -968,7 +1013,8 @@ ctkErrorLogLevel::LogLevel ctkDICOMRetrieve::DCMTKLogLevel() const } //------------------------------------------------------------------------------ -bool ctkDICOMRetrieve::moveStudy(const QString& studyInstanceUID) +bool ctkDICOMRetrieve::moveStudy(const QString& studyInstanceUID, + const QString& patientID) { if (studyInstanceUID.isEmpty()) { @@ -977,11 +1023,12 @@ bool ctkDICOMRetrieve::moveStudy(const QString& studyInstanceUID) } Q_D(ctkDICOMRetrieve); logger.debug("Starting moveStudy"); - return d->move(studyInstanceUID, "", "", ctkDICOMRetrieve::RetrieveStudy); + return d->move(patientID, studyInstanceUID, "", "", ctkDICOMRetrieve::RetrieveStudy); } //------------------------------------------------------------------------------ -bool ctkDICOMRetrieve::getStudy(const QString& studyInstanceUID) +bool ctkDICOMRetrieve::getStudy(const QString& studyInstanceUID, + const QString& patientID) { if (studyInstanceUID.isEmpty()) { @@ -990,69 +1037,75 @@ bool ctkDICOMRetrieve::getStudy(const QString& studyInstanceUID) } Q_D(ctkDICOMRetrieve); logger.debug("Starting getStudy"); - return d->get(studyInstanceUID, "", "", ctkDICOMRetrieve::RetrieveStudy); + return d->get(patientID, studyInstanceUID, "", "", ctkDICOMRetrieve::RetrieveStudy); } //------------------------------------------------------------------------------ bool ctkDICOMRetrieve::moveSeries(const QString& studyInstanceUID, - const QString& seriesInstanceUID) + const QString& seriesInstanceUID, + const QString& patientID) { - if (studyInstanceUID.isEmpty() || seriesInstanceUID.isEmpty()) + if (studyInstanceUID.isEmpty() || + seriesInstanceUID.isEmpty()) { - logger.error("Cannot receive series: Either Study or Series Instance UID empty."); + logger.error("Cannot receive series: Study or Series Instance UID empty."); return false; } Q_D(ctkDICOMRetrieve); logger.debug("Starting moveSeries"); - return d->move(studyInstanceUID, seriesInstanceUID, "", ctkDICOMRetrieve::RetrieveSeries); + return d->move(patientID, studyInstanceUID, seriesInstanceUID, "", ctkDICOMRetrieve::RetrieveSeries); } //------------------------------------------------------------------------------ bool ctkDICOMRetrieve::getSeries(const QString& studyInstanceUID, - const QString& seriesInstanceUID) + const QString& seriesInstanceUID, + const QString& patientID) { - if (studyInstanceUID.isEmpty() || seriesInstanceUID.isEmpty()) + if (studyInstanceUID.isEmpty() || + seriesInstanceUID.isEmpty()) { - logger.error("Cannot receive series: Either Study or Series Instance UID empty."); + logger.error("Cannot receive series: Study or Series Instance UID empty."); return false; } Q_D(ctkDICOMRetrieve); logger.debug("Starting getSeries"); - return d->get(studyInstanceUID, seriesInstanceUID, "", ctkDICOMRetrieve::RetrieveSeries); + return d->get(patientID, studyInstanceUID, seriesInstanceUID, "", ctkDICOMRetrieve::RetrieveSeries); } //------------------------------------------------------------------------------ -bool ctkDICOMRetrieve::moveSOPInstance(const QString &studyInstanceUID, - const QString &seriesInstanceUID, - const QString &SOPInstanceUID) +bool ctkDICOMRetrieve::moveSOPInstance(const QString& studyInstanceUID, + const QString& seriesInstanceUID, + const QString& SOPInstanceUID, + const QString& patientID) { if (studyInstanceUID.isEmpty() || seriesInstanceUID.isEmpty() || SOPInstanceUID.isEmpty()) { - logger.error("Cannot receive SOPInstance: Either Study, Series or SOP Instance UID empty."); + logger.error("Cannot receive SOPInstance: Study, Series or SOP Instance UID empty."); return false; } Q_D(ctkDICOMRetrieve); logger.debug("Starting moveSOPInstance"); - return d->move(studyInstanceUID, seriesInstanceUID, SOPInstanceUID, ctkDICOMRetrieve::RetrieveSOPInstance); + return d->move(patientID, studyInstanceUID, seriesInstanceUID, SOPInstanceUID, ctkDICOMRetrieve::RetrieveSOPInstance); } //------------------------------------------------------------------------------ -bool ctkDICOMRetrieve::getSOPInstance(const QString &studyInstanceUID, - const QString &seriesInstanceUID, - const QString &SOPInstanceUID) +bool ctkDICOMRetrieve::getSOPInstance(const QString& studyInstanceUID, + const QString& seriesInstanceUID, + const QString& SOPInstanceUID, + const QString& patientID) { if (studyInstanceUID.isEmpty() || seriesInstanceUID.isEmpty() || SOPInstanceUID.isEmpty()) { - logger.error("Cannot receive SOPInstance: Either Study, Series or SOP Instance UID empty."); + logger.error("Cannot receive SOPInstance: Study, Series or SOP Instance UID empty."); return false; } Q_D(ctkDICOMRetrieve); logger.debug("Starting getSOPInstance"); - return d->get(studyInstanceUID, seriesInstanceUID, SOPInstanceUID, ctkDICOMRetrieve::RetrieveSOPInstance); + return d->get(patientID, studyInstanceUID, seriesInstanceUID, SOPInstanceUID, ctkDICOMRetrieve::RetrieveSOPInstance); } //------------------------------------------------------------------------------ diff --git a/Libs/DICOM/Core/ctkDICOMRetrieve.h b/Libs/DICOM/Core/ctkDICOMRetrieve.h index 0365ff5959..0449e95986 100644 --- a/Libs/DICOM/Core/ctkDICOMRetrieve.h +++ b/Libs/DICOM/Core/ctkDICOMRetrieve.h @@ -110,6 +110,9 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMRetrieve : public QObject Q_INVOKABLE void setTaskUID(const QString& taskUID); Q_INVOKABLE QString taskUID() const; + /// Patient ID from from the last get operation. + QString patientID() const; + /// Study instance UID from from the last get operation. QString studyInstanceUID() const; @@ -131,21 +134,27 @@ public Q_SLOTS: /// Use CMOVE to ask peer host to store data to move destination Q_INVOKABLE bool moveSOPInstance(const QString& studyInstanceUID, const QString& seriesInstanceUID, - const QString& SOPInstanceUID); + const QString& SOPInstanceUID, + const QString& patientID = ""); /// Use CMOVE to ask peer host to store data to move destination Q_INVOKABLE bool moveSeries(const QString& studyInstanceUID, - const QString& seriesInstanceUID); + const QString& seriesInstanceUID, + const QString& patientID = ""); /// Use CMOVE to ask peer host to store data to move destination - Q_INVOKABLE bool moveStudy(const QString& studyInstanceUID); + Q_INVOKABLE bool moveStudy(const QString& studyInstanceUID, + const QString& patientID = ""); /// Use CGET to ask peer host to store data to us Q_INVOKABLE bool getSOPInstance(const QString& studyInstanceUID, const QString& seriesInstanceUID, - const QString& SOPInstanceUID); + const QString& SOPInstanceUID, + const QString& patientID = ""); /// Use CGET to ask peer host to store data to us Q_INVOKABLE bool getSeries(const QString& studyInstanceUID, - const QString& seriesInstanceUID); + const QString& seriesInstanceUID, + const QString& patientID = ""); /// Use CGET to ask peer host to store data to us - Q_INVOKABLE bool getStudy(const QString& studyInstanceUID); + Q_INVOKABLE bool getStudy(const QString& studyInstanceUID, + const QString& patientID = ""); /// Cancel the current operation Q_INVOKABLE void cancel(); diff --git a/Libs/DICOM/Core/ctkDICOMRetrieveTask.cpp b/Libs/DICOM/Core/ctkDICOMRetrieveTask.cpp index 681b1baadc..d830b182ae 100644 --- a/Libs/DICOM/Core/ctkDICOMRetrieveTask.cpp +++ b/Libs/DICOM/Core/ctkDICOMRetrieveTask.cpp @@ -38,6 +38,7 @@ ctkDICOMRetrieveTaskPrivate::ctkDICOMRetrieveTaskPrivate(ctkDICOMRetrieveTask* o this->Server = new ctkDICOMServer; this->RetrieveLevel = ctkDICOMRetrieveTask::DICOMLevel::Studies; + this->PatientID = ""; this->StudyInstanceUID = ""; this->SeriesInstanceUID = ""; this->SOPInstanceUID = ""; @@ -133,7 +134,8 @@ void ctkDICOMRetrieveTask::run() switch(d->RetrieveLevel) { case DICOMLevel::Studies: - if (!d->Retrieve->getStudy(d->StudyInstanceUID)) + if (!d->Retrieve->getStudy(d->StudyInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -142,7 +144,8 @@ void ctkDICOMRetrieveTask::run() break; case DICOMLevel::Series: if (!d->Retrieve->getSeries(d->StudyInstanceUID, - d->SeriesInstanceUID)) + d->SeriesInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -152,7 +155,8 @@ void ctkDICOMRetrieveTask::run() case DICOMLevel::Instances: if (!d->Retrieve->getSOPInstance(d->StudyInstanceUID, d->SeriesInstanceUID, - d->SOPInstanceUID)) + d->SOPInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -165,7 +169,8 @@ void ctkDICOMRetrieveTask::run() switch(d->RetrieveLevel) { case DICOMLevel::Studies: - if (!d->Retrieve->moveStudy(d->StudyInstanceUID)) + if (!d->Retrieve->moveStudy(d->StudyInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -174,7 +179,8 @@ void ctkDICOMRetrieveTask::run() break; case DICOMLevel::Series: if (!d->Retrieve->moveSeries(d->StudyInstanceUID, - d->SeriesInstanceUID)) + d->SeriesInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -184,7 +190,8 @@ void ctkDICOMRetrieveTask::run() case DICOMLevel::Instances: if (!d->Retrieve->moveSOPInstance(d->StudyInstanceUID, d->SeriesInstanceUID, - d->SOPInstanceUID)) + d->SOPInstanceUID, + d->PatientID)) { this->setIsFinished(true); emit canceled(); @@ -255,6 +262,20 @@ void ctkDICOMRetrieveTask::deleteSeriesTaskResults(ctkDICOMTaskResults *taskResu d->Retrieve->deleteSeriesTaskResults(taskResults); } +//---------------------------------------------------------------------------- +void ctkDICOMRetrieveTask::setPatientID(const QString &patientID) +{ + Q_D(ctkDICOMRetrieveTask); + d->PatientID = patientID; +} + +//---------------------------------------------------------------------------- +QString ctkDICOMRetrieveTask::patientID() const +{ + Q_D(const ctkDICOMRetrieveTask); + return d->PatientID; +} + //---------------------------------------------------------------------------- void ctkDICOMRetrieveTask::setStudyInstanceUID(const QString& studyInstanceUID) { diff --git a/Libs/DICOM/Core/ctkDICOMRetrieveTask.h b/Libs/DICOM/Core/ctkDICOMRetrieveTask.h index 29bc245eb9..711bb0e57c 100644 --- a/Libs/DICOM/Core/ctkDICOMRetrieveTask.h +++ b/Libs/DICOM/Core/ctkDICOMRetrieveTask.h @@ -76,6 +76,10 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMRetrieveTask : public ctkAbstractTask Q_INVOKABLE ctkDICOMServer* server() const; Q_INVOKABLE void setServer(ctkDICOMServer* server); + /// Patient ID + void setPatientID(const QString& patientID); + QString patientID() const; + /// Study instance UID void setStudyInstanceUID(const QString& studyInstanceUID); QString studyInstanceUID() const; diff --git a/Libs/DICOM/Core/ctkDICOMRetrieveTask_p.h b/Libs/DICOM/Core/ctkDICOMRetrieveTask_p.h index c1a84f1f55..b8f30244a2 100644 --- a/Libs/DICOM/Core/ctkDICOMRetrieveTask_p.h +++ b/Libs/DICOM/Core/ctkDICOMRetrieveTask_p.h @@ -47,6 +47,7 @@ class ctkDICOMRetrieveTaskPrivate : public QObject ctkDICOMServer *Server; ctkDICOMRetrieve *Retrieve; + QString PatientID; QString StudyInstanceUID; QString SeriesInstanceUID; QString SOPInstanceUID; diff --git a/Libs/DICOM/Core/ctkDICOMServer.cpp b/Libs/DICOM/Core/ctkDICOMServer.cpp index e0d5ab169c..0f025b8130 100644 --- a/Libs/DICOM/Core/ctkDICOMServer.cpp +++ b/Libs/DICOM/Core/ctkDICOMServer.cpp @@ -66,7 +66,7 @@ ctkDICOMServerPrivate::ctkDICOMServerPrivate(ctkDICOMServer& obj) this->QueryRetrieveEnabled = true; this->StorageEnabled = true; this->KeepAssociationOpen = false; - this->ConnectionTimeout = 3; + this->ConnectionTimeout = 10; this->RetrieveProtocol = ctkDICOMServer::RetrieveProtocol::CGET; this->ProxyServer = nullptr; } diff --git a/Libs/DICOM/Core/ctkDICOMServer.h b/Libs/DICOM/Core/ctkDICOMServer.h index db1e12bcbf..f9dc13e1e9 100644 --- a/Libs/DICOM/Core/ctkDICOMServer.h +++ b/Libs/DICOM/Core/ctkDICOMServer.h @@ -99,7 +99,7 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMServer : public QObject /// multiple requests (default true) void setKeepAssociationOpen(const bool keepOpen); bool keepAssociationOpen(); - /// connection timeout in seconds, default 3 s. + /// connection timeout in seconds, default 10 s. void setConnectionTimeout(const int timeout); int connectionTimeout(); /// proxy server diff --git a/Libs/DICOM/Core/ctkDICOMTaskPool.cpp b/Libs/DICOM/Core/ctkDICOMTaskPool.cpp index 775c8bed9e..ce33fde938 100644 --- a/Libs/DICOM/Core/ctkDICOMTaskPool.cpp +++ b/Libs/DICOM/Core/ctkDICOMTaskPool.cpp @@ -400,7 +400,8 @@ void ctkDICOMTaskPool::queryInstances(const QString& patientID, } //---------------------------------------------------------------------------- -void ctkDICOMTaskPool::retrieveStudy(const QString &studyInstanceUID, +void ctkDICOMTaskPool::retrieveStudy(const QString &patientID, + const QString &studyInstanceUID, QThread::Priority priority) { Q_D(ctkDICOMTaskPool); @@ -415,6 +416,7 @@ void ctkDICOMTaskPool::retrieveStudy(const QString &studyInstanceUID, ctkDICOMRetrieveTask *task = new ctkDICOMRetrieveTask(); task->setServer(server.data()); task->setRetrieveLevel(ctkDICOMRetrieveTask::DICOMLevel::Studies); + task->setPatientID(patientID); task->setStudyInstanceUID(studyInstanceUID); task->setAutoDelete(false); @@ -431,7 +433,8 @@ void ctkDICOMTaskPool::retrieveStudy(const QString &studyInstanceUID, } //---------------------------------------------------------------------------- -void ctkDICOMTaskPool::retrieveSeries(const QString &studyInstanceUID, +void ctkDICOMTaskPool::retrieveSeries(const QString &patientID, + const QString &studyInstanceUID, const QString &seriesInstanceUID, QThread::Priority priority) { @@ -447,6 +450,7 @@ void ctkDICOMTaskPool::retrieveSeries(const QString &studyInstanceUID, ctkDICOMRetrieveTask *task = new ctkDICOMRetrieveTask(); task->setServer(server.data()); task->setRetrieveLevel(ctkDICOMRetrieveTask::DICOMLevel::Series); + task->setPatientID(patientID); task->setStudyInstanceUID(studyInstanceUID); task->setSeriesInstanceUID(seriesInstanceUID); task->setAutoDelete(false); @@ -466,7 +470,8 @@ void ctkDICOMTaskPool::retrieveSeries(const QString &studyInstanceUID, } //---------------------------------------------------------------------------- -void ctkDICOMTaskPool::retrieveSOPInstance(const QString &studyInstanceUID, +void ctkDICOMTaskPool::retrieveSOPInstance(const QString &patientID, + const QString &studyInstanceUID, const QString &seriesInstanceUID, const QString &SOPInstanceUID, bool trackThumbnailUID, @@ -493,6 +498,7 @@ void ctkDICOMTaskPool::retrieveSOPInstance(const QString &studyInstanceUID, ctkDICOMRetrieveTask *task = new ctkDICOMRetrieveTask(); task->setServer(server.data()); task->setRetrieveLevel(ctkDICOMRetrieveTask::DICOMLevel::Instances); + task->setPatientID(patientID); task->setStudyInstanceUID(studyInstanceUID); task->setSeriesInstanceUID(seriesInstanceUID); task->setSOPInstanceUID(SOPInstanceUID); @@ -1160,21 +1166,22 @@ void ctkDICOMTaskPool::onTaskStarted() if (queryTask) { logger.debug(d->loggerQueryReport(queryTask, "started")); + emit this->taskStarted("Query"); } ctkDICOMRetrieveTask* retrieveTask = qobject_cast(this->sender()); if (retrieveTask) { logger.debug(d->loggerRetrieveReport(retrieveTask, "started")); + emit this->taskStarted("Retrieve"); } ctkDICOMStorageListenerTask* listenerTask = qobject_cast(this->sender()); if (listenerTask) { logger.debug(d->loggerListenerReport(listenerTask, "started")); + emit this->taskStarted("Listener"); } - - emit this->taskStarted(task); } //---------------------------------------------------------------------------- @@ -1200,6 +1207,7 @@ void ctkDICOMTaskPool::onTaskFinished() { emit this->progressTaskDetail(nullptr); } + emit this->taskFinished("Query"); } ctkDICOMRetrieveTask* retrieveTask = qobject_cast(this->sender()); @@ -1228,10 +1236,10 @@ void ctkDICOMTaskPool::onTaskFinished() ctkDICOMRetrieveTask* newRetrieveTask = new ctkDICOMRetrieveTask(); newRetrieveTask->setServer(proxyServer); newRetrieveTask->setRetrieveLevel(retrieveTask->retrieveLevel()); + newRetrieveTask->setPatientID(retrieveTask->patientID()); newRetrieveTask->setStudyInstanceUID(retrieveTask->studyInstanceUID()); newRetrieveTask->setSeriesInstanceUID(retrieveTask->seriesInstanceUID()); newRetrieveTask->setSOPInstanceUID(retrieveTask->sopInstanceUID()); - newRetrieveTask->setNumberOfRetry(retrieveTask->numberOfRetry() + 1); newRetrieveTask->setTaskUID(newTaskUID); newRetrieveTask->setAutoDelete(false); @@ -1268,15 +1276,15 @@ void ctkDICOMTaskPool::onTaskFinished() // no results from the retrieve emit this->progressTaskDetail(nullptr); } + emit this->taskFinished("Retrieve"); } ctkDICOMStorageListenerTask* listenerTask = qobject_cast(this->sender()); if (listenerTask) { logger.debug(d->loggerListenerReport(listenerTask, "finished")); + emit this->taskFinished("Listener"); } - - emit this->taskFinished(task); } //---------------------------------------------------------------------------- @@ -1294,6 +1302,7 @@ void ctkDICOMTaskPool::onTaskCanceled() if (queryTask) { logger.debug(d->loggerQueryReport(queryTask, "canceled")); + emit this->taskCanceled("Query"); QString taskUID = queryTask->taskUID(); if (queryTask->numberOfRetry() < d->MaximumNumberOfRetry && !queryTask->isStopped()) @@ -1312,8 +1321,8 @@ void ctkDICOMTaskPool::onTaskCanceled() } else if (!queryTask->isStopped()) { - logger.debug(d->loggerQueryReport(queryTask, "failed")); - emit this->progressTaskDetail(nullptr); + logger.error(d->loggerQueryReport(queryTask, "failed")); + emit this->taskFailed("Query"); } this->deleteTask(taskUID); @@ -1323,6 +1332,7 @@ void ctkDICOMTaskPool::onTaskCanceled() if (retrieveTask) { logger.debug(d->loggerRetrieveReport(retrieveTask, "canceled")); + emit this->taskCanceled("Retrieve"); QString taskUID = retrieveTask->taskUID(); if (retrieveTask->numberOfRetry() < d->MaximumNumberOfRetry && !retrieveTask->isStopped()) @@ -1341,7 +1351,8 @@ void ctkDICOMTaskPool::onTaskCanceled() } else if (!retrieveTask->isStopped()) { - logger.debug(d->loggerRetrieveReport(retrieveTask, "failed")); + logger.error(d->loggerRetrieveReport(retrieveTask, "failed")); + emit this->taskFailed("Retrieve"); } this->deleteTask(taskUID); @@ -1351,6 +1362,7 @@ void ctkDICOMTaskPool::onTaskCanceled() if (listenerTask) { logger.debug(d->loggerListenerReport(listenerTask, "canceled")); + emit this->taskCanceled("Listener"); QString taskUID = listenerTask->taskUID(); if (listenerTask->numberOfRetry() < d->MaximumNumberOfRetry && !listenerTask->isStopped()) @@ -1367,13 +1379,12 @@ void ctkDICOMTaskPool::onTaskCanceled() } else if (!listenerTask->isStopped()) { - logger.debug(d->loggerListenerReport(listenerTask, "failed")); + logger.error(d->loggerListenerReport(listenerTask, "failed")); + emit this->taskFailed("Listener"); } this->deleteTask(taskUID); } - - emit this->taskCanceled(task); } //---------------------------------------------------------------------------- diff --git a/Libs/DICOM/Core/ctkDICOMTaskPool.h b/Libs/DICOM/Core/ctkDICOMTaskPool.h index 92a862c20b..5bddcce743 100644 --- a/Libs/DICOM/Core/ctkDICOMTaskPool.h +++ b/Libs/DICOM/Core/ctkDICOMTaskPool.h @@ -79,18 +79,21 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMTaskPool : public ctkAbstractTaskPool /// Retrieve Study. /// The method spans a ctkDICOMRetrieveTask for each server. - Q_INVOKABLE void retrieveStudy(const QString& studyInstanceUID, + Q_INVOKABLE void retrieveStudy(const QString& patientID, + const QString& studyInstanceUID, QThread::Priority priority = QThread::LowPriority); /// Retrieve Series. /// The method spans a ctkDICOMRetrieveTask for each server. - Q_INVOKABLE void retrieveSeries(const QString& studyInstanceUID, + Q_INVOKABLE void retrieveSeries(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, QThread::Priority priority = QThread::LowPriority); /// Retrieve SOPInstance. /// The method spans a ctkDICOMRetrieveTask for each server. - Q_INVOKABLE void retrieveSOPInstance(const QString& studyInstanceUID, + Q_INVOKABLE void retrieveSOPInstance(const QString& patientID, + const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString &SOPInstanceUID, bool trackThumbnailUID = false, @@ -204,9 +207,10 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMTaskPool : public ctkAbstractTaskPool Q_SIGNALS: void progressTaskDetail(ctkDICOMTaskResults*); void progressBarTaskDetail(ctkDICOMTaskResults*); - void taskStarted(ctkAbstractTask* task); - void taskFinished(ctkAbstractTask* task); - void taskCanceled(ctkAbstractTask* task); + void taskStarted(QString taskType); + void taskFinished(QString taskType); + void taskCanceled(QString taskType); + void taskFailed(QString taskType); public Q_SLOTS: void onTaskStarted(); diff --git a/Libs/DICOM/Widgets/Resources/UI/Icons/query.svg b/Libs/DICOM/Widgets/Resources/UI/Icons/query.svg index fe587cefbf..c611282e40 100644 --- a/Libs/DICOM/Widgets/Resources/UI/Icons/query.svg +++ b/Libs/DICOM/Widgets/Resources/UI/Icons/query.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/Libs/DICOM/Widgets/Resources/UI/Icons/restore.svg b/Libs/DICOM/Widgets/Resources/UI/Icons/restore.svg deleted file mode 100644 index 884575fd06..0000000000 --- a/Libs/DICOM/Widgets/Resources/UI/Icons/restore.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/Libs/DICOM/Widgets/Resources/UI/Icons/wait.svg b/Libs/DICOM/Widgets/Resources/UI/Icons/wait.svg index ac48f36b50..5b6554fd6a 100644 --- a/Libs/DICOM/Widgets/Resources/UI/Icons/wait.svg +++ b/Libs/DICOM/Widgets/Resources/UI/Icons/wait.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Libs/DICOM/Widgets/Resources/UI/ctkDICOMWidget.qrc b/Libs/DICOM/Widgets/Resources/UI/ctkDICOMWidget.qrc index 9f39ba990a..47aecafd7b 100644 --- a/Libs/DICOM/Widgets/Resources/UI/ctkDICOMWidget.qrc +++ b/Libs/DICOM/Widgets/Resources/UI/ctkDICOMWidget.qrc @@ -6,7 +6,6 @@ Icons/import.svg Icons/loaded.svg Icons/patient.svg - Icons/query.svg Icons/visible.svg Icons/warning.svg Icons/load.svg @@ -15,8 +14,8 @@ Icons/more_vert.svg Icons/add.svg Icons/dns.svg - Icons/restore.svg Icons/save.svg + Icons/query.svg Icons/wait.svg diff --git a/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp b/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp index 2b41fc06c9..4bd2e51f3e 100644 --- a/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp @@ -253,12 +253,16 @@ void ctkDICOMSeriesItemWidgetPrivate::createThumbnail(ctkDICOMTaskResults *taskR if (this->IsCloud && (typeOfTask == ctkDICOMTaskResults::TaskType::FileIndexing || typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances)) { - this->TaskPool->retrieveSOPInstance(this->StudyInstanceUID, + this->TaskPool->retrieveSOPInstance(this->PatientID, + this->StudyInstanceUID, this->SeriesInstanceUID, this->CentralFrameSOPInstanceUID, true, QThread::NormalPriority); - + return; + } + if (this->IsCloud && typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance) + { // Get all the others frames if (numberOfFrames > 1) { @@ -269,13 +273,12 @@ void ctkDICOMSeriesItemWidgetPrivate::createThumbnail(ctkDICOMTaskResults *taskR continue; } - this->TaskPool->retrieveSeries(this->StudyInstanceUID, + this->TaskPool->retrieveSeries(this->PatientID, + this->StudyInstanceUID, this->SeriesInstanceUID); break; } } - - return; } } @@ -710,6 +713,7 @@ void ctkDICOMSeriesItemWidget::updateGUIFromTaskPool(ctkDICOMTaskResults *taskRe taskResults->typeOfTask() != ctkDICOMTaskResults::TaskType::RetrieveSeries && taskResults->typeOfTask() != ctkDICOMTaskResults::TaskType::StoreSOPInstance && taskResults->typeOfTask() != ctkDICOMTaskResults::TaskType::StoreSeries) || + taskResults->patientID() != d->PatientID || taskResults->studyInstanceUID() != d->StudyInstanceUID || taskResults->seriesInstanceUID() != d->SeriesInstanceUID) { diff --git a/Libs/DICOM/Widgets/ctkDICOMServerNodeWidget2.cpp b/Libs/DICOM/Widgets/ctkDICOMServerNodeWidget2.cpp index 4ba46b89e2..8778c77ebd 100644 --- a/Libs/DICOM/Widgets/ctkDICOMServerNodeWidget2.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMServerNodeWidget2.cpp @@ -299,11 +299,11 @@ void ctkDICOMServerNodeWidget2Private::disconnectTaskPool() return; } - ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskStarted(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskStarted(QString)), q, SLOT(updateGUIState())); - ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskFinished(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskFinished(QString)), q, SLOT(updateGUIState())); - ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskCanceled(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::disconnect(this->TaskPool.data(), SIGNAL(taskCanceled(QString)), q, SLOT(updateGUIState())); } @@ -316,11 +316,11 @@ void ctkDICOMServerNodeWidget2Private::connectTaskPool() return; } - ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskStarted(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskStarted(QString)), q, SLOT(updateGUIState())); - ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskFinished(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskFinished(QString)), q, SLOT(updateGUIState())); - ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskCanceled(ctkAbstractTask*)), + ctkDICOMServerNodeWidget2::connect(this->TaskPool.data(), SIGNAL(taskCanceled(QString)), q, SLOT(updateGUIState())); } diff --git a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp index 86e6c2b96a..8f88a4aa89 100644 --- a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp @@ -392,6 +392,8 @@ void ctkDICOMVisualBrowserWidgetPrivate::disconnectTaskPool() ctkDICOMVisualBrowserWidget::disconnect(this->TaskPool.data(), SIGNAL(progressTaskDetail(ctkDICOMTaskResults*)), q, SLOT(updateGUIFromTaskPool(ctkDICOMTaskResults*))); + ctkDICOMVisualBrowserWidget::disconnect(this->TaskPool.data(), SIGNAL(taskFailed(QString)), + q, SLOT(onTaskFailed(QString))); ctkDICOMVisualBrowserWidget::disconnect(this->TaskPool->indexer(), SIGNAL(progress(int)), q, SLOT(onIndexingProgress(int))); ctkDICOMVisualBrowserWidget::disconnect(this->TaskPool->indexer(), SIGNAL(progressStep(QString)),q, SLOT(onIndexingProgressStep(QString))); ctkDICOMVisualBrowserWidget::disconnect(this->TaskPool->indexer(), SIGNAL(progressDetail(QString)), q, SLOT(onIndexingProgressDetail(QString))); @@ -409,6 +411,8 @@ void ctkDICOMVisualBrowserWidgetPrivate::connectTaskPool() ctkDICOMVisualBrowserWidget::connect(this->TaskPool.data(), SIGNAL(progressTaskDetail(ctkDICOMTaskResults*)), q, SLOT(updateGUIFromTaskPool(ctkDICOMTaskResults*))); + ctkDICOMVisualBrowserWidget::connect(this->TaskPool.data(), SIGNAL(taskFailed(QString)), + q, SLOT(onTaskFailed(QString))); ctkDICOMVisualBrowserWidget::connect(this->TaskPool->indexer(), SIGNAL(progress(int)), q, SLOT(onIndexingProgress(int))); ctkDICOMVisualBrowserWidget::connect(this->TaskPool->indexer(), SIGNAL(progressStep(QString)),q, SLOT(onIndexingProgressStep(QString))); ctkDICOMVisualBrowserWidget::connect(this->TaskPool->indexer(), SIGNAL(progressDetail(QString)), q, SLOT(onIndexingProgressDetail(QString))); @@ -2129,8 +2133,8 @@ void ctkDICOMVisualBrowserWidget::onQueryPatient() d->FilteringSeriesDescriptionSearchBox->setStyleSheet(d->FilteringSeriesDescriptionSearchBox->styleSheet() + background); d->FilteringModalityCheckableComboBox->setStyleSheet(d->FilteringModalityCheckableComboBox->styleSheet() + background); - d->WarningPushButton->setText("No filters have been set and no patients have been found in the local database." - "\nPlease set at least one filter to query the servers"); + d->WarningPushButton->setText(tr("No filters have been set and no patients have been found in the local database." + "\nPlease set at least one filter to query the servers")); d->WarningPushButton->show(); d->patientsTabMenuToolButton->hide(); return; @@ -2192,10 +2196,32 @@ void ctkDICOMVisualBrowserWidget::updateGUIFromTaskPool(ctkDICOMTaskResults *tas return; } + if (taskResults->datasets().count() == 0) + { + d->WarningPushButton->setText(tr("The query provided no results. Please refine your filters.")); + d->WarningPushButton->show(); + } + d->createPatients(); d->TaskPool->deleteTask(taskResults->taskUID()); } +//------------------------------------------------------------------------------ +void ctkDICOMVisualBrowserWidget::onTaskFailed(QString taskType) +{ + Q_D(ctkDICOMVisualBrowserWidget); + if (taskType == "Query") + { + d->updateFiltersWarnings(); + d->ProgressFrame->hide(); + d->QueryPatientPushButton->setIcon(QIcon(":/Icons/query.svg")); + } + + d->WarningPushButton->setText(tr("%1 task failed to fetch the data." + "\nFor more information please open the error report console. \n").arg(taskType)); + d->WarningPushButton->show(); +} + //------------------------------------------------------------------------------ void ctkDICOMVisualBrowserWidget::onPatientItemChanged(int index) { @@ -2754,6 +2780,9 @@ void ctkDICOMVisualBrowserWidget::onStop(bool stopPersistentTasks) QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); d->TaskPool->stopAllTasks(stopPersistentTasks); + d->updateFiltersWarnings(); + d->ProgressFrame->hide(); + d->QueryPatientPushButton->setIcon(QIcon(":/Icons/query.svg")); QApplication::restoreOverrideCursor(); } @@ -2824,7 +2853,7 @@ bool ctkDICOMVisualBrowserWidget::confirmDeleteSelectedUIDs(QStringList uids) confirmDeleteDialog.addButton(tr("Delete"), QMessageBox::AcceptRole); confirmDeleteDialog.addButton(tr("Cancel"), QMessageBox::RejectRole); - confirmDeleteDialog.setDontShowAgainSettingsKey("MainWindow/DontConfirmDeleteSelected"); + confirmDeleteDialog.setDontShowAgainSettingsKey("VisualDICOMBrowser/DontConfirmDeleteSelected"); int response = confirmDeleteDialog.exec(); diff --git a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.h b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.h index 4aa98e1562..63f921a327 100644 --- a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.h +++ b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.h @@ -297,6 +297,7 @@ public Q_SLOTS: void onFilteringDateComboBoxChanged(int); void onQueryPatient(); void updateGUIFromTaskPool(ctkDICOMTaskResults*); + void onTaskFailed(QString); void onPatientItemChanged(int); void onClose(); void onLoad();