Skip to content

Commit

Permalink
ENH: Add Visual DICOM Browser (#1165)
Browse files Browse the repository at this point in the history
ENH: Add Visual DICOM Browser

Introduces the `ctkDICOMVisualBrowserWidget`, which improves the threaded
execution of the following operations:

- Filtering and navigation with thumbnails of local database and servers results
- Import from file system to local database
- Query/Retrieve from servers (DIMSE C-GET/C-MOVE )
- Storage listener
- Send (emits only a signal for the moment, requires external implementation)
- Remove (only from local database, not from server)
- Metadata exploration

In addition, the commit introduces the following classes:

* `Core` classes:
  * `ctkAbstractJob`
  * `ctkAbstractScheduler`
  * `ctkAbstractWorker`
* `DICOM/Core` classes:
  * `ctkDICOMEcho`
  * `ctkDICOMInserter`
  * `ctkDICOMInserterJob`
  * `ctkDICOMInserterWorker`
  * `ctkDICOMJob`
  * `ctkDICOMJobResponseSet`
  * `ctkDICOMQueryJob`
  * `ctkDICOMQueryWorker`
  * `ctkDICOMRetrieveJob`
  * `ctkDICOMRetrieveWorker`
  * `ctkDICOMScheduler`
  * `ctkDICOMServer`
  * `ctkDICOMStorageListener`
  * `ctkDICOMStorageListenerJob`
  * `ctkDICOMStorageListenerWorker`
* `DICOM/Widget`classes:
  * `ctkDICOMPatientItemWidget`
  * `ctkDICOMSeriesItemWidget`
  * `ctkDICOMServerNodeWidget2`
  * `ctkDICOMStudyItemWidget`

Co-authored-by: Davide Punzo <[email protected]>
Co-authored-by: Andras Lasso <[email protected]>
Co-authored-by: Jean-Christophe Fillion-Robin <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2024
1 parent 45f33c8 commit 8a0717d
Show file tree
Hide file tree
Showing 140 changed files with 22,537 additions and 804 deletions.
40 changes: 40 additions & 0 deletions Applications/ctkDICOMVisualBrowser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
project(ctkDICOMVisualBrowser)

#
# See CTK/CMake/ctkMacroBuildApp.cmake for details
#

# Source files
set(KIT_SRCS
ctkDICOMVisualBrowserMain.cpp
)

# Headers that should run through moc
set(KIT_MOC_SRCS
)

# UI files
set(KIT_UI_FORMS
)

# Resources
set(KIT_resources
)

# Target libraries - See CMake/ctkFunctionGetTargetLibraries.cmake
# The following macro will read the target libraries from the file 'target_libraries.cmake'
ctkFunctionGetTargetLibraries(KIT_target_libraries)

ctkMacroBuildApp(
NAME ${PROJECT_NAME}
SRCS ${KIT_SRCS}
MOC_SRCS ${KIT_MOC_SRCS}
UI_FORMS ${KIT_UI_FORMS}
TARGET_LIBRARIES ${KIT_target_libraries}
RESOURCES ${KIT_resources}
)

# Testing
if(BUILD_TESTING)
add_subdirectory(Testing)
endif()
1 change: 1 addition & 0 deletions Applications/ctkDICOMVisualBrowser/Testing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(Cpp)
21 changes: 21 additions & 0 deletions Applications/ctkDICOMVisualBrowser/Testing/Cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
set(KIT ${PROJECT_NAME})

create_test_sourcelist(Tests ${KIT}CppTests.cpp
ctkDICOMVisualBrowserTest1.cpp
)

SET (TestsToRun ${Tests})
REMOVE (TestsToRun ${KIT}CppTests.cpp)

# Target libraries - See CMake/ctkFunctionGetTargetLibraries.cmake
# The following macro will read the target libraries from the file '<KIT_SOURCE_DIR>/target_libraries.cmake'
ctkFunctionGetTargetLibraries(KIT_target_libraries ${${KIT}_SOURCE_DIR})

ctk_add_executable_utf8(${KIT}CppTests ${Tests})
target_link_libraries(${KIT}CppTests ${KIT_target_libraries})

#
# Add Tests
#

SIMPLE_TEST(ctkDICOMVisualBrowserTest1 $<TARGET_FILE:ctkDICOMVisualBrowser>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*=========================================================================
Library: CTK
Copyright (c) Kitware Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/

// Qt includes
#include <QCoreApplication>
#include <QProcess>

// STD includes
#include <cstdlib>
#include <iostream>

int ctkDICOMVisualBrowserTest1(int argc, char * argv [])
{
QCoreApplication app(argc, argv);
if (app.arguments().count() != 2)
{
std::cerr << "Line " << __LINE__ << " - Failed to run " << argv[0] << "\n"
<< "Usage:\n"
<< " " << argv[0] << " /path/to/ctkDICOM";
return EXIT_FAILURE;
}
QString command = app.arguments().at(1);
QProcess process;
process.start(command, /* arguments= */ QStringList());
bool res = process.waitForStarted();
if (!res)
{
std::cerr << '\"' << qPrintable(command) << '\"'
<< " didn't start correctly" << std::endl;
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
process.kill();
res = process.waitForFinished();
if (!res)
{
std::cerr << '\"' << qPrintable(command) << '\"'
<< " failed to terminate" << std::endl;
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
return res ? EXIT_SUCCESS : EXIT_FAILURE;
}
99 changes: 99 additions & 0 deletions Applications/ctkDICOMVisualBrowser/ctkDICOMVisualBrowserMain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*=========================================================================
Library: CTK
Copyright (c) Isomics Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/

// Qt includes
#include <QApplication>
#include <QLabel>
#include <QDir>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QResource>
#include <QSettings>
#include <QVBoxLayout>

// CTK widget includes
#include <ctkCollapsibleGroupBox.h>
#include <ctkDirectoryButton.h>
#include <ctkDICOMVisualBrowserWidget.h>

// STD includes
#include <iostream>

int main(int argc, char** argv)
{
QApplication app(argc, argv);

app.setOrganizationName("commontk");
app.setOrganizationDomain("commontk.org");
app.setApplicationName("ctkDICOM");

// set up Qt resource files
QResource::registerResource("./Resources/ctkDICOM.qrc");

QWidget mainWidget;
mainWidget.setObjectName(QString::fromUtf8("MainWidget"));
mainWidget.setWindowTitle(QString::fromUtf8("DICOM Visual Browser"));

QVBoxLayout mainLayout;
mainLayout.setObjectName(QString::fromUtf8("mainLayout"));
mainLayout.setContentsMargins(1, 1, 1, 1);

QHBoxLayout topLayout;
topLayout.setObjectName(QString::fromUtf8("topLayout"));
topLayout.setContentsMargins(1, 1, 1, 1);

QLabel databaseNameLabel;
databaseNameLabel.setObjectName(QString::fromUtf8("DatabaseNameLabel"));
databaseNameLabel.setMaximumSize(QSize(100, 30));
topLayout.addWidget(&databaseNameLabel);

ctkDirectoryButton directoryButton;
directoryButton.setObjectName(QString::fromUtf8("DirectoryButton"));
directoryButton.setMinimumSize(QSize(200, 30));
if (argc > 1)
{
directoryButton.setDirectory(argv[1]);
}
topLayout.addWidget(&directoryButton);

mainLayout.addLayout(&topLayout);

ctkDICOMVisualBrowserWidget DICOMVisualBrowser;
DICOMVisualBrowser.setObjectName(QString::fromUtf8("DICOMVisualBrowser"));
DICOMVisualBrowser.setDatabaseDirectorySettingsKey("DatabaseDirectory");
DICOMVisualBrowser.setMinimumSize(QSize(1000, 1000));
// set up the database
if (argc > 1)
{
DICOMVisualBrowser.setDatabaseDirectory(argv[1]);
}

DICOMVisualBrowser.serverSettingsGroupBox()->setChecked(true);
QObject::connect(&directoryButton, SIGNAL(directoryChanged(const QString&)),
&DICOMVisualBrowser, SLOT(setDatabaseDirectory(const QString&)));

mainLayout.addWidget(&DICOMVisualBrowser);

mainWidget.setLayout(&mainLayout);

mainWidget.show();

return app.exec();
}
9 changes: 9 additions & 0 deletions Applications/ctkDICOMVisualBrowser/target_libraries.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# See CMake/ctkFunctionGetTargetLibraries.cmake
#
# This file should list the libraries required to build the current CTK application.
#

set(target_libraries
CTKDICOMWidgets
)
6 changes: 6 additions & 0 deletions CMake/ctkMacroSetupQt.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ macro(ctkMacroSetupQt)

# See https://github.com/commontk/CTK/wiki/Maintenance#updates-of-required-qt-components

if(CTK_LIB_Widgets
OR CTK_LIB_DICOM/Widgets
)
list(APPEND CTK_QT5_COMPONENTS Svg)
endif()

if(CTK_LIB_Widgets
OR CTK_LIB_Scripting/Python/Core_PYTHONQT_WRAP_QTXML
)
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ ctk_app_option(ctkDICOM2
"Build the new DICOM example application (experimental)" OFF
CTK_ENABLE_DICOM AND CTK_BUILD_EXAMPLES)

ctk_app_option(ctkDICOMVisualBrowser
"Build the new DICOM example application (experimental)" OFF
CTK_ENABLE_DICOM AND CTK_BUILD_EXAMPLES)

ctk_app_option(ctkDICOMIndexer
"Build the DICOM example application" OFF
CTK_ENABLE_DICOM AND CTK_BUILD_EXAMPLES)
Expand Down
20 changes: 20 additions & 0 deletions Libs/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ set(KIT_SRCS
ctkAbstractFactory.tpp
ctkAbstractFileBasedFactory.h
ctkAbstractFileBasedFactory.tpp
ctkAbstractJob.cpp
ctkAbstractJob.h
ctkAbstractObjectFactory.h
ctkAbstractObjectFactory.tpp
ctkAbstractPluginFactory.h
Expand All @@ -30,6 +32,8 @@ set(KIT_SRCS
ctkAbstractQObjectFactory.tpp
ctkAbstractLibraryFactory.h
ctkAbstractLibraryFactory.tpp
ctkAbstractWorker.cpp
ctkAbstractWorker.h
ctkBackTrace.cpp
ctkBooleanMapper.cpp
ctkBooleanMapper.h
Expand Down Expand Up @@ -65,6 +69,9 @@ set(KIT_SRCS
ctkFileLogger.cpp
ctkFileLogger.h
ctkHighPrecisionTimer.cpp
ctkJobScheduler.cpp
ctkJobScheduler.h
ctkJobScheduler_p.h
ctkLinearValueProxy.cpp
ctkLinearValueProxy.h
ctkLogger.cpp
Expand Down Expand Up @@ -100,6 +107,8 @@ endif()

# Headers that should run through moc
set(KIT_MOC_SRCS
ctkAbstractJob.h
ctkAbstractWorker.h
ctkBooleanMapper.h
ctkCallback.h
ctkCommandLineParser.h
Expand All @@ -111,6 +120,8 @@ set(KIT_MOC_SRCS
ctkErrorLogQtMessageHandler.h
ctkErrorLogTerminalOutput.h
ctkFileLogger.h
ctkJobScheduler.h
ctkJobScheduler_p.h
ctkLinearValueProxy.h
ctkLogger.h
ctkModelTester.h
Expand All @@ -122,6 +133,15 @@ set(KIT_MOC_SRCS
ctkWorkflowTransitions.h
)

# Abstract class should not be wrapped !
set_source_files_properties(
ctkAbstractJob.h
ctkAbstractWorker.h
ctkJobScheduler.h
ctkJobScheduler_p.h
WRAP_EXCLUDE
)

# UI files
set(KIT_UI_FORMS
)
Expand Down
Loading

0 comments on commit 8a0717d

Please sign in to comment.