From 4bd69267558e0efae5082a02429db075c5a5263c Mon Sep 17 00:00:00 2001 From: Andras Lasso Date: Wed, 3 Nov 2021 14:20:16 -0400 Subject: [PATCH] ENH: Add API to select items in the DICOM browser This allows selecting patient/study/series in the DICOM browser GUI. Co-authored-by: Jean-Christophe Fillion-Robin --- Libs/DICOM/Widgets/ctkDICOMBrowser.cpp | 49 +++++++++++++++++++++ Libs/DICOM/Widgets/ctkDICOMBrowser.h | 5 +++ Libs/DICOM/Widgets/ctkDICOMTableManager.cpp | 21 +++++++++ Libs/DICOM/Widgets/ctkDICOMTableManager.h | 7 +++ Libs/DICOM/Widgets/ctkDICOMTableView.cpp | 30 +++++++++++-- Libs/DICOM/Widgets/ctkDICOMTableView.h | 5 +++ 6 files changed, 114 insertions(+), 3 deletions(-) diff --git a/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp b/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp index 81a183c89e..2ae26f892c 100644 --- a/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp @@ -1749,3 +1749,52 @@ void ctkDICOMBrowser::onIndexingComplete(int patientsAdded, int studiesAdded, in // allow users of this widget to know that the process has finished emit directoryImported(); } + +//---------------------------------------------------------------------------- +void ctkDICOMBrowser::setSelectedItems(ctkDICOMModel::IndexType level, QStringList uids) +{ + Q_D(ctkDICOMBrowser); + if (level == ctkDICOMModel::PatientType) + { + d->dicomTableManager->setCurrentPatientsSelection(uids); + } + else if (level == ctkDICOMModel::StudyType) + { + // Select parent patient to make sure the requested studies + // are listed in the study table + QStringList patientUids; + for (const QString& uid : uids) + { + QString patientUid = d->DICOMDatabase->patientForStudy(uid); + if (!patientUids.contains(patientUid)) + { + patientUids.append(patientUid); + } + } + this->setSelectedItems(ctkDICOMModel::PatientType, patientUids); + + d->dicomTableManager->setCurrentStudiesSelection(uids); + } + else if (level == ctkDICOMModel::SeriesType) + { + // Select parent patients and studies to make sure the requested series + // are listed in the series table + QStringList studyUids; + for (const QString& uid : uids) + { + QString studyUid = d->DICOMDatabase->studyForSeries(uid); + if (!studyUids.contains(studyUid)) + { + studyUids.append(studyUid); + } + } + // selecting the study will select the patients as well + this->setSelectedItems(ctkDICOMModel::StudyType, studyUids); + + d->dicomTableManager->setCurrentSeriesSelection(uids); + } + else + { + qWarning() << Q_FUNC_INFO << " failed: invalid level"; + } +} diff --git a/Libs/DICOM/Widgets/ctkDICOMBrowser.h b/Libs/DICOM/Widgets/ctkDICOMBrowser.h index 1c52d735eb..17e309d425 100644 --- a/Libs/DICOM/Widgets/ctkDICOMBrowser.h +++ b/Libs/DICOM/Widgets/ctkDICOMBrowser.h @@ -241,6 +241,11 @@ public Q_SLOTS: void removeSelectedItems(ctkDICOMModel::IndexType level); + /// Select items in a browser table. + /// Selection is also updated at levels higher than the specified level + /// (otherwise items would not be available at the current level). + void setSelectedItems(ctkDICOMModel::IndexType level, QStringList uids); + Q_SIGNALS: /// Emitted when directory is changed void databaseDirectoryChanged(const QString&); diff --git a/Libs/DICOM/Widgets/ctkDICOMTableManager.cpp b/Libs/DICOM/Widgets/ctkDICOMTableManager.cpp index a4ae6d1020..7e7981c35d 100644 --- a/Libs/DICOM/Widgets/ctkDICOMTableManager.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMTableManager.cpp @@ -251,6 +251,27 @@ QStringList ctkDICOMTableManager::currentSeriesSelection() return d->seriesTable->currentSelection(); } +//------------------------------------------------------------------------------ +void ctkDICOMTableManager::setCurrentPatientsSelection(const QStringList& uids) +{ + Q_D(ctkDICOMTableManager); + d->patientsTable->setCurrentSelection(uids); +} + +//------------------------------------------------------------------------------ +void ctkDICOMTableManager::setCurrentStudiesSelection(const QStringList& uids) +{ + Q_D(ctkDICOMTableManager); + d->studiesTable->setCurrentSelection(uids); +} + +//------------------------------------------------------------------------------ +void ctkDICOMTableManager::setCurrentSeriesSelection(const QStringList& uids) +{ + Q_D(ctkDICOMTableManager); + d->seriesTable->setCurrentSelection(uids); +} + //------------------------------------------------------------------------------ void ctkDICOMTableManager::onPatientsQueryChanged(const QStringList &uids) { diff --git a/Libs/DICOM/Widgets/ctkDICOMTableManager.h b/Libs/DICOM/Widgets/ctkDICOMTableManager.h index 4f78e13119..cccd549aa6 100644 --- a/Libs/DICOM/Widgets/ctkDICOMTableManager.h +++ b/Libs/DICOM/Widgets/ctkDICOMTableManager.h @@ -85,6 +85,13 @@ class CTK_DICOM_WIDGETS_EXPORT ctkDICOMTableManager : public QWidget Q_INVOKABLE QStringList currentStudiesSelection(); Q_INVOKABLE QStringList currentSeriesSelection(); + /** + * @brief Set the current selection of the dicomTableViews + */ + Q_INVOKABLE void setCurrentPatientsSelection(const QStringList& uids); + Q_INVOKABLE void setCurrentStudiesSelection(const QStringList& uids); + Q_INVOKABLE void setCurrentSeriesSelection(const QStringList& uids); + void setDynamicTableLayout(bool); bool dynamicTableLayout() const; diff --git a/Libs/DICOM/Widgets/ctkDICOMTableView.cpp b/Libs/DICOM/Widgets/ctkDICOMTableView.cpp index a163dc5e5e..4544b76364 100644 --- a/Libs/DICOM/Widgets/ctkDICOMTableView.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMTableView.cpp @@ -292,7 +292,7 @@ void ctkDICOMTableViewPrivate::applyColumnProperties() int columnIndicesCount = columnIndicesByVisualIndex.size(); for (int i=0; i columnIndicesByVisualIndex[j+1]) @@ -306,7 +306,7 @@ void ctkDICOMTableViewPrivate::applyColumnProperties() // Change column order according to weights (use bubble sort) for (int i=0; i columnWeights[j+1]) @@ -799,6 +799,30 @@ QStringList ctkDICOMTableView::currentSelection() const return uids; } +//------------------------------------------------------------------------------ +void ctkDICOMTableView::setCurrentSelection(const QStringList& uids) +{ + Q_D(const ctkDICOMTableView); + + QAbstractItemModel* tableModel = d->tblDicomDatabaseView->model(); + int numberOfRows = tableModel->rowCount(); + for (int row = 0; row < numberOfRows; ++row) + { + QModelIndex index = tableModel->index(row, 0); + QString uid = index.data().toString(); + bool needToSelect = uids.contains(uid); + if (d->tblDicomDatabaseView->selectionModel()->isSelected(index) == needToSelect) + { + // selection state is already correct + continue; + } + QItemSelectionModel::QItemSelectionModel::SelectionFlags flags = QFlags(); + flags.setFlag(needToSelect ? QItemSelectionModel::Select : QItemSelectionModel::Deselect); + flags.setFlag(QItemSelectionModel::Rows); + d->tblDicomDatabaseView->selectionModel()->select(index, flags); + } +} + //------------------------------------------------------------------------------ bool ctkDICOMTableView::filterActive() { @@ -851,7 +875,7 @@ bool ctkDICOMTableView::setBatchUpdate(bool enable) { this->onInstanceAdded(); } - } + } d->batchUpdateModificationPending = false; d->batchUpdateInstanceAddedPending = false; return !d->batchUpdate; diff --git a/Libs/DICOM/Widgets/ctkDICOMTableView.h b/Libs/DICOM/Widgets/ctkDICOMTableView.h index 75cf260fd2..43f2aef6c7 100644 --- a/Libs/DICOM/Widgets/ctkDICOMTableView.h +++ b/Libs/DICOM/Widgets/ctkDICOMTableView.h @@ -219,6 +219,11 @@ class CTK_DICOM_WIDGETS_EXPORT ctkDICOMTableView : public QWidget */ Q_INVOKABLE QStringList currentSelection() const; + /** + * @brief Select rows corresponding to the provided uids. + */ + Q_INVOKABLE void setCurrentSelection(const QStringList& uids); + /** * @brief Getting the UIDs for all rows * @return a QStringList with the uids for all rows