20 #define QT_NO_CAST_TO_ASCII 27 #include <QMessageBox> 28 #include <QFileDialog> 41 #include <dcmtk/dcmimgle/dcmimage.h> 42 #include <dcmtk/dcmdata/dcrledrg.h> 43 #include <dcmtk/dcmjpeg/djdecode.h> 44 #include <dcmtk/dcmjpeg/dipijpeg.h> 46 #include <dcmtk/dcmimage/diregist.h> 61 QString dateToString(
const QDate & date) {
62 if (date == QDate()) {
66 return date.toString(
"yyyyMMdd");
118 if ( _instance == 0 ) {
127 if (_instance != 0) {
133 QtDcmManager::QtDcmManager(QObject *parent)
138 d->useConverter =
true;
143 d->outputdirMode = DIALOG;
145 d->patientName =
"*";
147 d->patientBirthDate =
"";
149 d->serieDescription =
"*";
150 d->studyDescription =
"*";
153 d->mainWidget = NULL;
154 d->patientsTreeWidget = NULL;
155 d->studiesTreeWidget = NULL;
156 d->seriesTreeWidget = NULL;
158 d->importWidget = NULL;
159 d->previewWidget = NULL;
160 d->serieInfoWidget = NULL;
162 this->createTemporaryDirs();
165 QtDcmManager::~QtDcmManager()
167 this->deleteTemporaryDirs();
175 d->mainWidget = widget;
176 if ( ! d->mainWidget.isNull() ) {
185 d->patientsTreeWidget = widget;
190 d->studiesTreeWidget = widget;
195 d->seriesTreeWidget = widget;
200 d->importWidget = widget;
201 QObject::connect ( d->importWidget->importButton, &QPushButton::clicked,
207 d->previewWidget = widget;
212 d->serieInfoWidget = widget;
217 return d->outputdirMode;
222 d->outputdirMode =
mode;
227 if ( d->serieInfoWidget ) {
228 d->serieInfoWidget->elementCountLabel->setText (
"" );
229 d->serieInfoWidget->institutionLabel->setText (
"" );
230 d->serieInfoWidget->operatorLabel->setText (
"" );
236 const QString &institution,
237 const QString &name )
239 if ( d->serieInfoWidget ) {
240 d->serieInfoWidget->elementCountLabel->setText ( eltCount );
241 d->serieInfoWidget->institutionLabel->setText ( institution );
242 d->serieInfoWidget->operatorLabel->setText ( name );
248 if ( d->previewWidget ) {
249 d->previewWidget->imageLabel->setPixmap ( QPixmap() );
257 QMessageBox msgBox(d->mainWidget);
258 msgBox.setIcon ( QMessageBox::Critical );
259 msgBox.setText ( message );
266 QMessageBox msgBox ( d->mainWidget );
267 msgBox.setIcon ( QMessageBox::Information );
268 msgBox.setText ( info );
274 if ( d->mainWidget->pacsComboBox->count() ) {
275 d->seriesToImport.clear();
286 d->seriesToImport.clear();
289 finder->
findStudiesScu ( patientName, d->studyDescription, dateToString(d->date1), dateToString(d->date2) );
295 d->seriesToImport.clear();
298 finder->
findSeriesScu ( patientName, studyUid, d->studyDescription, d->serieDescription, d->modality );
311 if ( !d->patientsTreeWidget.isNull() ) {
312 QTreeWidgetItem * patientItem =
new QTreeWidgetItem ( d->patientsTreeWidget->invisibleRootItem() );
313 patientItem->setText ( 0, infosMap[
"Name"] );
314 patientItem->setText ( 1, infosMap[
"ID"] );
315 patientItem->setText ( 2, QDate::fromString ( infosMap[
"Birthdate"],
"yyyyMMdd" ).toString (
"dd/MM/yyyy" ) );
316 patientItem->setText ( 3, infosMap[
"Sex"] );
322 if ( !d->studiesTreeWidget.isNull() ) {
323 QTreeWidgetItem * studyItem =
new QTreeWidgetItem ( d->studiesTreeWidget->invisibleRootItem() );
324 studyItem->setText ( 0, infosMap[
"Description"] );
325 studyItem->setText ( 1, QDate::fromString ( infosMap[
"Date"],
"yyyyMMdd" ).toString (
"dd/MM/yyyy" ) );
326 studyItem->setData ( 2, 0, infosMap[
"UID"] );
327 studyItem->setText ( 2, infosMap[
"UID"] );
328 studyItem->setData ( 3, 0, infosMap[
"ID"] );
334 if ( !d->seriesTreeWidget.isNull() ) {
335 QTreeWidgetItem * serieItem =
new QTreeWidgetItem ( d->seriesTreeWidget->invisibleRootItem() );
336 serieItem->setText ( 0, infosMap[
"Description"] );
337 serieItem->setText ( 1, infosMap[
"Modality"] );
338 serieItem->setText ( 2, QDate::fromString ( infosMap[
"Date"],
"yyyyMMdd" ).toString (
"dd/MM/yyyy" ) );
339 serieItem->setText ( 3, infosMap[
"ID"] );
340 serieItem->setData ( 4, 0, QVariant ( infosMap[
"InstanceCount"] ) );
341 serieItem->setData ( 5, 0, QVariant ( infosMap[
"Institution"] ) );
342 serieItem->setData ( 6, 0, QVariant ( infosMap[
"Operator"] ) );
343 serieItem->setCheckState ( 0, Qt::Unchecked );
349 d->listImages.append ( image );
351 d->mapImages.insert ( number, image );
357 if ( d->dicomdir.isEmpty() ) {
365 if ( ! ( status = d->dfile.loadFile ( d->dicomdir.toUtf8().data() ) ).good() ) {
369 this->findPatientsDicomdir();
374 d->seriesToImport.clear();
383 d->seriesToImport.clear();
391 const QString &studyUID )
393 d->seriesToImport.clear();
410 if ( !d->tempDir.exists() ) {
415 qApp->processEvents();
429 connect ( mover, &QtDcmMoveDicomdir::finished,
431 connect ( mover, &QtDcmMoveDicomdir::finished,
432 mover, &QtDcmMoveDicomdir::deleteLater);
446 connect ( mover, &QtDcmMoveScu::finished,
448 connect ( mover, &QtDcmMoveScu::finished,
449 mover, &QtDcmMoveScu::deleteLater);
454 qWarning() <<
"Move mode not supported";
461 if ( !d->tempDir.exists() ) {
465 if ( !d->listImages.size() ) {
469 if ( d->listImages.size() < elementIndex ) {
473 QString imageId = d->listImages[elementIndex];
475 if ( d->mapImages.size() && d->mapImages.contains ( elementIndex ) ) {
476 imageId = d->mapImages[elementIndex];
486 mover->
setSeries ( QStringList() << uid );
490 connect(mover, &QtDcmMoveDicomdir::finished,
491 mover, &QtDcmMoveDicomdir::deleteLater);
498 this->clearPreview();
499 emit gettingPreview();
502 if ( d->seriesTreeWidget->currentItem() ) {
503 modality = d->seriesTreeWidget->currentItem()->text ( 1 );
506 QString filename ( d->tempDir.absolutePath() +
"/" + uid +
"/" + modality +
"." + imageId );
507 if ( QFile ( filename ).exists() ) {
508 makePreview ( filename );
514 mover->
setSeries ( QStringList() << uid );
518 connect(mover, &QtDcmMoveScu::finished,
519 mover, &QtDcmMoveScu::deleteLater);
525 qWarning() <<
"Move mode not supported";
535 if ( this->useExternalConverter() ) {
536 if ( this->seriesToImportSize() != 0 ) {
538 QFileDialog dialog( d->mainWidget );
539 dialog.setFileMode ( QFileDialog::Directory );
540 dialog.setOption ( QFileDialog::ShowDirsOnly,
true );
543 if (!QDir::drives().isEmpty()) {
544 dialog.setDirectory ( QDir::drives().first().absoluteDir() );
547 dialog.setWindowTitle ( tr (
"Export directory" ) );
549 if ( dialog.exec() ) {
550 directory = dialog.selectedFiles() [0];
553 if ( !directory.isEmpty() ) {
555 this->setOutputDirectory ( directory );
556 this->moveSelectedSeries();
560 if ( QDir ( this->outputDirectory() ).exists() ) {
561 this->moveSelectedSeries();
567 this->setOutputDirectory (
"" );
568 this->moveSelectedSeries();
574 if ( this->seriesToImportSize() != 0 ) {
575 this->setOutputDirectory ( directory );
576 this->moveSelectedSeries();
582 if ( d->useConverter ) {
583 qDebug() <<
"Starting reconstruction of series" << serie;
592 qDebug() <<
"Conversion complete";
594 if ( number == this->seriesToImportSize() - 1 ) {
595 emit importFinished();
602 if ( d->importWidget ) {
603 d->importWidget->importProgressBar->setValue ( 0 );
609 if ( d->importWidget ) {
610 d->importWidget->importProgressBar->setValue ( i );
612 qApp->processEvents();
615 void QtDcmManager::createTemporaryDirs()
618 QDir
tempDir = QDir ( QDir::tempPath() );
621 const QString randName = QUuid::createUuid().toString();
623 if ( !tempDir.exists (
"qtdcm" ) )
624 tempDir.mkdir (
"qtdcm" );
626 QDir qtdcmDir = QDir ( QDir::tempPath() + QDir::separator() +
"qtdcm" );
628 if ( !qtdcmDir.exists ( randName ) ) {
629 qtdcmDir.mkdir ( randName );
632 d->tempDir = QDir ( qtdcmDir.absolutePath() + QDir::separator() + randName );
637 QDir qtdcmTmpDir(QDir::tempPath() + QDir::separator() +
"qtdcm");
638 if(!qtdcmTmpDir.removeRecursively()) {
639 qWarning() <<
"Cannot remove recursively temporary directory" << qtdcmTmpDir.absolutePath();
643 void QtDcmManager::generateCurrentSerieDir()
645 if ( !d->serieId.isEmpty() ) {
646 d->currentSerieDir = d->tempDir.absolutePath() + QDir::separator() + d->serieId;
647 d->tempDir.mkdir ( d->serieId );
651 void QtDcmManager::deleteCurrentSerieDir()
654 const QStringList listFiles = d->currentSerieDir.entryList ( QDir::Files, QDir::Name );
656 for (
int i = 0; i < listFiles.size(); i++ ) {
657 d->currentSerieDir.remove ( listFiles.at ( i ) );
661 if ( !d->tempDir.rmdir ( d->serieId ) ) {
662 qDebug() << tr (
"Probleme lors de la suppression du répertoire temporaire" );
668 DcmRLEDecoderRegistration::registerCodecs ( OFFalse, OFFalse );
669 DJDecoderRegistration::registerCodecs ( EDC_photometricInterpretation, EUC_default, EPC_default, OFFalse );
671 file.loadFile ( filename.toLatin1().data() );
672 DcmDataset * dset = file.getDataset();
673 DicomImage* dcimage =
new DicomImage ( dset, file.getDataset()->getOriginalXfer(), CIF_MayDetachPixelData );
676 if ( dcimage != NULL ) {
677 dcimage->setNoDisplayFunction();
678 dcimage->hideAllOverlays();
679 dcimage->setNoVoiTransformation();
681 if ( dcimage->getStatus() == EIS_Normal ) {
682 Uint32 *pixelData = ( Uint32 * ) ( dcimage->getOutputData ( 32 ) );
684 if ( pixelData != NULL ) {
685 Uint8 *colored =
new Uint8[dcimage->getWidth() * dcimage->getHeight() * 4];
686 Uint8 *col = colored;
687 Uint32 *p = pixelData;
691 Uint32 p_min = UINT_LEAST32_MAX;
693 Uint32 p_min = std::numeric_limits<Uint32>::max();
696 for (
unsigned i = 0; i < dcimage->getWidth(); ++i ) {
697 for (
unsigned j = 0; j < dcimage->getHeight(); ++j, ++p ) {
708 double a = 4294967295.f / ( ( double ) p_max - (
double ) p_min );
714 for (
unsigned i = 0; i < dcimage->getWidth(); ++i ) {
715 for (
unsigned j = 0; j < dcimage->getHeight(); ++j, ++p ) {
716 *col = ( Uint8 ) ( ( 255.f / 4294967295.f ) * ( a * ( ( double ) ( *p ) - ( double ) p_min ) ) );
718 *col = ( Uint8 ) ( ( 255.f / 4294967295.f ) * ( a * ( ( double ) ( *p ) - ( double ) p_min ) ) );
720 *col = ( Uint8 ) ( ( 255.f / 4294967295.f ) * ( a * ( ( double ) ( *p ) - ( double ) p_min ) ) );
727 QImage image ( colored, dcimage->getWidth(), dcimage->getHeight(), QImage::Format_ARGB32 );
729 if ( d->previewWidget ) {
730 d->previewWidget->imageLabel->setPixmap ( QPixmap::fromImage ( image.scaled ( 130,130 ), Qt::AutoColor ) );
741 DcmRLEDecoderRegistration::cleanup();
742 DJDecoderRegistration::cleanup();
757 if ( ! ( status = d->dfile.loadFile ( d->dicomdir.toUtf8().data() ) ).good() ) {
769 d->outputDir = directory;
774 return d->currentPacs;
786 return d->patientName;
807 if ( d->patientsTreeWidget && d->patientsTreeWidget->currentItem() ) {
808 birthdate = d->patientsTreeWidget->currentItem()->data ( 2,0 ).toString();
817 if ( d->patientsTreeWidget && d->patientsTreeWidget->currentItem() ) {
818 sex = d->patientsTreeWidget->currentItem()->data ( 3,0 ).toString();
827 if ( d->studiesTreeWidget && d->studiesTreeWidget->currentItem() ) {
828 examDate = d->studiesTreeWidget->currentItem()->data ( 1,0 ).toString();
841 return d->serieDescription;
851 return d->studyDescription;
906 return d->listImages;
911 d->listImages.clear();
912 d->mapImages.clear();
922 return d->currentSerieDir.absolutePath();
927 if ( !d->seriesToImport.contains ( uid ) ) {
928 d->seriesToImport.append ( uid );
934 if ( d->seriesToImport.contains ( uid ) )
935 d->seriesToImport.removeOne ( uid );
940 d->seriesToImport.clear();
945 return d->seriesToImport.size();
950 return d->useConverter;
955 d->useConverter = use;
QStringList seriesToImport
Map of images (corresponding to listImages) with InstanceNumber tags used as keys.
void findPatientsScu()
Find SCU with Dcmtk code.
QString patientName
Current selected serie UID.
QDir tempDir
Directory containing current serie dicom slice.
void loadDicomdir()
This method read the dicomdir file and populate the patient treewidget.
void findImagesScu(const QString &seriesUID)
void moveSeriesFinished()
void setSeriesTreeWidget(QTreeWidget *widget)
QString serieDescription
Attribute for the end date of the query (usefull for date based queries)
static QtDcmPreferences * instance()
void setPatientsTreeWidget(QTreeWidget *widget)
QStringList images
List that contains patients resulting of a query or read from a CD.
void setSerieDescription(const QString &serieDescription)
Serie description setter.
QPointer< QtDcmImportWidget > importWidget
The pointer to the preview widget.
void findImagesDicomdir(const QString &serieUID)
QPointer< QTreeWidget > studiesTreeWidget
The pointer to the patients tree widget.
void removeSerieToImport(const QString &uid)
void setDcmItem(DcmItem *item)
QString patientSex
Attribute representing the patient id used to query PACS.
void getPreviewFromSelectedSerie(const QString &uid, int elementCount)
QtDcmServer currentPacs() const
QPointer< QtDcmPreviewWidget > previewWidget
The pointer to the series tree widget.
void findPatientsDicomdir()
void displayMessage(const QString &info)
Convenience method that display information message in a QMessageBox window.
QDir currentSerieDir
Output directory for reconstructed serie absolute path.
QString seriesDescription() const
Serie description getter.
void setImportDir(const QString &dir)
QString patientId() const
Patient id getter.
QList< QtDcmPatient > patients
This attribute is usefull for parsing the dicomdir.
QStringList listImages
List of image filename to export from a CD.
void setCurrentPacs(int index)
void previewSlice(const QString &filename)
void findSeriesScu(const QString &patientName, const QString &studyUID)
static QtDcmManager * instance()
QDate startDate() const
Study date getter.
QString patientBirthdate() const
void setSeries(const QStringList &series)
QList< QtDcmServer > servers() const
QtDcm server list getter.
void setListOfImages(const QStringList &images)
QMap< int, QString > mapImages
List of images uid in the current selected serie.
void findSeriesDicomdir(const QString &patientName, const QString &studyDescription)
This class is a representation of a dicom patient.
void updateProgressBar(int i)
This class is in charge of the different process (dcm2nii), pacs query/retrieve (dcm4chee), temporary directory creation and removing, PACS server settings.
void setOutputdirMode(QtDcmManager::eOutputdirMode mode)
QtDcmServer currentPacs
Output directory mode DIALOG or CUSTOM.
QString modality
Attribute representing the patient birthdate used to query PACS.
QString dicomdir() const
Return the dicomdir absolute path name.
QString outputDir
Dicomdir absolute file path.
void findPatientsScu(const QString &patientName)
void setSerieUID(const QString &uid)
QDate date2
Attribute for the begin date of the query (usefull for date based queries)
void setStudiesTreeWidget(QTreeWidget *widget)
void setImageId(const QString &id)
void displayErrorMessage(const QString &message)
Convenience method that display error message in a QMessageBox window.
void setPatientId(const QString &patientId)
Patient id setter.
QString studyDescription
Attibute representing the serie description used for query PACS.
void deleteTemporaryDirs()
This method try to delete the temporary directory when closing the QtDcm widget (Doesn't work for the...
void updateProgress(int i)
void findImages(const QString &seriesUID)
void foundSerie(const QMap< QString, QString > &infosMap)
void updatePacsComboBox()
Updates the PACS list in combo box.
void previewSlice(const QString &filename)
void setPatientGender(const QString &sex)
void updateSerieInfo(const QString &eltCount, const QString &institution, const QString &name)
QPointer< QtDcm > mainWidget
QList< QString > listOfImages() const
void setInputDirectory(const QString &dir)
void setPatientName(const QString &patientName)
Patient name setter.
void setOutputDirectory(const QString &directory)
Set the output directory.
void clearSeriesToImport()
QString patientName() const
Patient name getter.
void onSerieMoved(const QString &directory, const QString &uid, int number)
void updateProgress(int i)
void importToDirectory(const QString &directory)
void addSerieToImport(const QString &uid)
void foundPatient(const QMap< QString, QString > &infosMap)
void findImagesScu(const QString &uid)
QString currentSeriesDirectory() const
QPointer< QTreeWidget > seriesTreeWidget
The pointer to the studies tree widget.
void findStudiesScu(const QString &patientName)
void setEndDate(const QDate &date)
Study date setter.
eMoveMode mode() const
Mode getter.
void moveSelectedSeries()
QString modality() const
Study modality getter.
void setStudyDescription(const QString &studyDescription)
Study description setter.
void serieMoved(const QString &directory, const QString &uid, int number)
void setStartDate(const QDate &date)
Study date setter.
QString patientId
Attribute frepresenting the patient name used to query PACS.
QPointer< QtDcmSerieInfoWidget > serieInfoWidget
The pointer to the import widget.
QPointer< QTreeWidget > patientsTreeWidget
Current pacs index in the pacs list.
void setDcmItem(DcmItem *item)
void findStudiesScu(const QString &patientName)
QString outputDirectory() const
Return the output directory where the current serie will be reconstructed.
void setOutputFilename(const QString &fname)
void setSeries(const QStringList &series)
void setUseExternalConverter(bool use)
void setSerieInfoWidget(QtDcmSerieInfoWidget *widget)
void preferencesUpdated()
QString patientGender() const
void importSelectedSeries()
QtDcmManager::eOutputdirMode outputdirMode
Absolute filename of the dcm2nii program.
void findStudies(const QString &patientName)
void setOutputDirectory(const QString &dir)
void makePreview(const QString &filename)
void setMode(eMoveMode mode)
void setImportWidget(QtDcmImportWidget *widget)
DcmFileFormat dfile
Qtdcm temporary directory (/tmp/qtdcm on Unix)
void setSerieId(const QString &id)
QDate endDate() const
Study date getter.
void findSeriesScu(const QString &patientName, const QString &studyUID)
void findSeries(const QString &patientName, const QString &studyUid)
void foundStudy(const QMap< QString, QString > &infosMap)
void setImageId(const QString &uid)
void setTempDirectory(const QString &dir)
void setDicomdir(const QString &dicomdir)
Set the dicomdir file name.
This class is a representation of a Dicom PACS server.
void setModality(const QString &modality)
Study modality setter.
QtDcmManager::eOutputdirMode getOutputdirMode() const
void setPreviewWidget(QtDcmPreviewWidget *widget)
void setMode(eMoveMode eMoveMode)
void foundImage(const QString &image, int number)
QDate date1
Attibute for the modality of the search (MR, US, CT, etc)
void setOutputDir(const QString &dir)
QString serieId
Selected series list in the treview.
QtDcmManager::eMoveMode mode
Attibute representing the study description used for query PACS.
void setOutputDir(const QString &dir)
QString dcm2nii
Mode that determine the type of media (MEDIA or PACS)
void setImportDir(const QString &dir)
bool useConverter
The pointer to the serie info widget.
bool useExternalConverter() const
void findStudiesDicomdir(const QString &patientName)
void addPatient()
add patient in the list
This class contains the widget for managing Dicom data.
void setQtDcmWidget(QtDcm *widget)
void serieMoved(const QString &directory, const QString &serie, int number)
QString patientBirthDate
Attribute representing the patient sex used to query PACS.
QString studyDescription() const
Study description getter.