diff --git a/Libs/DICOM/Core/CMakeLists.txt b/Libs/DICOM/Core/CMakeLists.txt index b817caa484..d2b7d8c60f 100644 --- a/Libs/DICOM/Core/CMakeLists.txt +++ b/Libs/DICOM/Core/CMakeLists.txt @@ -35,6 +35,8 @@ set(KIT_SRCS ctkDICOMTester.h ctkDICOMUtil.cpp ctkDICOMUtil.h + ctkDICOMDisplayedFieldGeneratorRuleFactory.h + ctkDICOMDisplayedFieldGeneratorRuleFactory.cpp ctkDICOMDisplayedFieldGeneratorAbstractRule.h ctkDICOMDisplayedFieldGeneratorDefaultRule.h ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp @@ -42,12 +44,12 @@ set(KIT_SRCS ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.cpp - ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h - ctkDICOMDisplayedFieldGeneratorSeriesImageCount.cpp - ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h - ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.cpp - ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h - ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.cpp + ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h + ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.cpp + ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h + ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.cpp + ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h + ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.cpp ) # Abstract class should not be wrapped ! @@ -63,6 +65,7 @@ set(KIT_MOC_SRCS ctkDICOMDatabase.h ctkDICOMDisplayedFieldGenerator.h ctkDICOMDisplayedFieldGenerator_p.h + ctkDICOMDisplayedFieldGeneratorRuleFactory.h ctkDICOMIndexer.h ctkDICOMIndexer_p.h ctkDICOMFilterProxyModel.h diff --git a/Libs/DICOM/Core/Resources/dicom-schema.sql b/Libs/DICOM/Core/Resources/dicom-schema.sql index b8b76d3c01..0f9d3da5b7 100644 --- a/Libs/DICOM/Core/Resources/dicom-schema.sql +++ b/Libs/DICOM/Core/Resources/dicom-schema.sql @@ -14,6 +14,7 @@ DROP TABLE IF EXISTS 'Patients' ; DROP TABLE IF EXISTS 'Series' ; DROP TABLE IF EXISTS 'Studies' ; DROP TABLE IF EXISTS 'ColumnDisplayProperties' ; +DROP TABLE IF EXISTS 'DisplayedFieldGeneratorRules' ; DROP TABLE IF EXISTS 'Directories' ; DROP INDEX IF EXISTS 'ImagesFilenameIndex' ; @@ -22,7 +23,7 @@ DROP INDEX IF EXISTS 'SeriesStudyIndex' ; DROP INDEX IF EXISTS 'StudiesPatientIndex' ; CREATE TABLE 'SchemaInfo' ( 'Version' VARCHAR(1024) NOT NULL ); -INSERT INTO 'SchemaInfo' VALUES('0.6.3'); +INSERT INTO 'SchemaInfo' VALUES('0.7.0'); CREATE TABLE 'Images' ( 'SOPInstanceUID' VARCHAR(64) NOT NULL, @@ -149,3 +150,9 @@ INSERT INTO 'ColumnDisplayProperties' VALUES('Series', 'DisplayedSize', INSERT INTO 'ColumnDisplayProperties' VALUES('Series', 'DisplayedCount', 'Count', 1, 5, '{"resizeMode":"resizeToContents"}'); INSERT INTO 'ColumnDisplayProperties' VALUES('Series', 'DisplayedNumberOfFrames', 'Number of frames', 0, 0, ''); INSERT INTO 'ColumnDisplayProperties' VALUES('Series', 'DisplayedFieldsUpdatedTimestamp', '', 0, 0, ''); + +CREATE TABLE 'DisplayedFieldGeneratorRules' ( + 'Name' VARCHAR(64) NOT NULL, + 'Enabled' INT NULL DEFAULT 1 , + 'Options' VARCHAR(255) NULL , + PRIMARY KEY ('Name') ); diff --git a/Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h b/Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h index 9b04ae0326..63f6f8adea 100644 --- a/Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h +++ b/Libs/DICOM/Core/ctkDICOMCorePythonQtDecorators.h @@ -25,6 +25,7 @@ #include // CTK includes +#include #include // NOTE: @@ -44,12 +45,29 @@ class ctkDICOMCorePythonQtDecorators : public QObject { } -public Q_SLOTS: +public slots: - // - // None yet - refer to other libs for examples - // + //---------------------------------------------------------------------------- + // ctkDICOMDisplayedFieldGeneratorRuleFactory + //---------------------------------------------------------------------------- + // static methods + + //---------------------------------------------------------------------------- + ctkDICOMDisplayedFieldGeneratorRuleFactory* static_ctkDICOMDisplayedFieldGeneratorRuleFactory_instance() + { + return ctkDICOMDisplayedFieldGeneratorRuleFactory::instance(); + } + + //---------------------------------------------------------------------------- + // instance methods + + //---------------------------------------------------------------------------- + bool registerDisplayedFieldGeneratorRule(ctkDICOMDisplayedFieldGeneratorRuleFactory* factory, + PythonQtPassOwnershipToCPP plugin) + { + return factory->registerDisplayedFieldGeneratorRule(plugin); + } }; //----------------------------------------------------------------------------- @@ -57,7 +75,7 @@ class PythonQtWrapper_CTKDICOMCore : public QObject { Q_OBJECT -public Q_SLOTS: +public slots: ctkErrorLogLevel::LogLevel static_ctk_dicomLogLevel() { return ctk::dicomLogLevel(); diff --git a/Libs/DICOM/Core/ctkDICOMDatabase.cpp b/Libs/DICOM/Core/ctkDICOMDatabase.cpp index 76571cee7b..186109bfcf 100644 --- a/Libs/DICOM/Core/ctkDICOMDatabase.cpp +++ b/Libs/DICOM/Core/ctkDICOMDatabase.cpp @@ -80,7 +80,7 @@ ctkDICOMDatabasePrivate::ctkDICOMDatabasePrivate(ctkDICOMDatabase& o) , TagCacheVerified(false) , DisplayedFieldsTableAvailable(false) , UseShortStoragePath(true) - , SchemaVersion("0.6.3") + , SchemaVersion("0.7.0") { this->resetLastInsertedValues(); this->DisplayedFieldGenerator = new ctkDICOMDisplayedFieldGenerator(q_ptr); @@ -103,7 +103,8 @@ void ctkDICOMDatabasePrivate::init(QString databaseFilename) } //------------------------------------------------------------------------------ -void ctkDICOMDatabasePrivate::registerCompressionLibraries(){ +void ctkDICOMDatabasePrivate::registerCompressionLibraries() +{ // Register the JPEG libraries in case we need them // (registration only happens once, so it's okay to call repeatedly) // register global JPEG decompression codecs @@ -1555,6 +1556,7 @@ void ctkDICOMDatabase::openDatabase(const QString databaseFile, const QString& c // Add displayed field generator's required tags to the pre-cached list to make // displayed field updates fast. QStringList tags = this->tagsToPrecache(); + d->DisplayedFieldGenerator->setDatabase(this); tags << d->DisplayedFieldGenerator->getRequiredTags(); tags.removeDuplicates(); this->setTagsToPrecache(tags); @@ -2980,8 +2982,6 @@ void ctkDICOMDatabase::updateDisplayedFields() QMap > displayedFieldsMapStudy; QMap > displayedFieldsMapPatient; - d->DisplayedFieldGenerator->setDatabase(this); - int progressValue = 0; emit displayedFieldsUpdateProgress(++progressValue); diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.cpp index a5136bbe89..f86fd05e3e 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.cpp @@ -23,16 +23,11 @@ // ctkDICOM includes #include "ctkLogger.h" +#include "ctkDICOMDatabase.h" #include "ctkDICOMDisplayedFieldGenerator.h" #include "ctkDICOMDisplayedFieldGenerator_p.h" - -#include "ctkDICOMDatabase.h" -#include "ctkDICOMDisplayedFieldGeneratorDefaultRule.h" -#include "ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h" -#include "ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h" -#include "ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h" -#include "ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h" -#include "ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h" +#include "ctkDICOMDisplayedFieldGeneratorAbstractRule.h" +#include "ctkDICOMDisplayedFieldGeneratorRuleFactory.h" //------------------------------------------------------------------------------ static ctkLogger logger("org.commontk.dicom.DICOMDisplayedFieldGenerator" ); @@ -47,38 +42,68 @@ ctkDICOMDisplayedFieldGeneratorPrivate::ctkDICOMDisplayedFieldGeneratorPrivate(c : q_ptr(&o) , Database(nullptr) { - // register commonly used rules - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorDefaultRule); - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule); - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorLastStudyDateRule); - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorSeriesImageCount); - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries); - this->AllRules.append(new ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies); - - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, this->AllRules) +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorPrivate::~ctkDICOMDisplayedFieldGeneratorPrivate() = default; + +//------------------------------------------------------------------------------ +void ctkDICOMDisplayedFieldGeneratorPrivate::setupEnabledDisplayedFieldGeneratorRules() +{ + if (!this->Database) + { + qCritical() << Q_FUNC_INFO << " failed: DICOM database needs to be set"; + return; + } + if (!this->GeneratorRules.isEmpty()) { + qWarning() << Q_FUNC_INFO << " : Generator rules have not been cleared before new update session"; + + this->clearDisplayedFieldGeneratorRules(); + } + + // Instantiate enabled rules registered in factory + this->GeneratorRules = + ctkDICOMDisplayedFieldGeneratorRuleFactory::instance()->copyEnabledDisplayedFieldGeneratorRules(this->Database); + + // Setup generator rules used in this update session + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, this->GeneratorRules) + { + // Set database + rule->setDatabase(this->Database); + // Register empty field names rule->registerEmptyFieldNames( this->EmptyFieldNamesSeries, this->EmptyFieldNamesStudies, this->EmptyFieldNamesPatients ); } + + //TODO: Process Options field in DisplayedFieldGeneratorRules table when has a concrete use. } //------------------------------------------------------------------------------ -ctkDICOMDisplayedFieldGeneratorPrivate::~ctkDICOMDisplayedFieldGeneratorPrivate() +void ctkDICOMDisplayedFieldGeneratorPrivate::clearDisplayedFieldGeneratorRules() { - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, this->AllRules) + // Delete generator rules and clear container + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, this->GeneratorRules) { delete rule; } - this->AllRules.clear(); + this->GeneratorRules.clear(); + + // Clear empty field names registered previously by the rules + this->EmptyFieldNamesSeries.clear(); + this->EmptyFieldNamesStudies.clear(); + this->EmptyFieldNamesPatients.clear(); } + //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // ctkDICOMDisplayedFieldGenerator methods //------------------------------------------------------------------------------ -ctkDICOMDisplayedFieldGenerator::ctkDICOMDisplayedFieldGenerator(QObject *parent):d_ptr(new ctkDICOMDisplayedFieldGeneratorPrivate(*this)) +ctkDICOMDisplayedFieldGenerator::ctkDICOMDisplayedFieldGenerator(QObject *parent) + : d_ptr(new ctkDICOMDisplayedFieldGeneratorPrivate(*this)) { Q_UNUSED(parent); } @@ -86,6 +111,8 @@ ctkDICOMDisplayedFieldGenerator::ctkDICOMDisplayedFieldGenerator(QObject *parent //------------------------------------------------------------------------------ ctkDICOMDisplayedFieldGenerator::~ctkDICOMDisplayedFieldGenerator() { + Q_D(ctkDICOMDisplayedFieldGenerator); + d->clearDisplayedFieldGeneratorRules(); } //------------------------------------------------------------------------------ @@ -94,13 +121,12 @@ QStringList ctkDICOMDisplayedFieldGenerator::getRequiredTags() Q_D(ctkDICOMDisplayedFieldGenerator); QStringList requiredTags; - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->AllRules) + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->GeneratorRules) { requiredTags << rule->getRequiredDICOMTags(); } requiredTags.removeDuplicates(); - // TODO: remove duplicates from requiredTags (maybe also sort) return requiredTags; } @@ -117,7 +143,7 @@ void ctkDICOMDisplayedFieldGenerator::updateDisplayedFieldsForInstance( QMap newFieldsSeries; QMap newFieldsStudy; QMap newFieldsPatient; - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->AllRules) + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->GeneratorRules) { QMap initialFieldsSeries = displayedFieldsForCurrentSeries; QMap initialFieldsStudy = displayedFieldsForCurrentStudy; @@ -138,7 +164,12 @@ void ctkDICOMDisplayedFieldGenerator::updateDisplayedFieldsForInstance( void ctkDICOMDisplayedFieldGenerator::startUpdate() { Q_D(ctkDICOMDisplayedFieldGenerator); - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->AllRules) + + // Re-initialize generator rules in case new ones have been registered or the rule options changed in the database + d->clearDisplayedFieldGeneratorRules(); + d->setupEnabledDisplayedFieldGeneratorRules(); + + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->GeneratorRules) { rule->startUpdate(); } @@ -150,7 +181,8 @@ void ctkDICOMDisplayedFieldGenerator::endUpdate(QMap > &displayedFieldsMapPatient) { Q_D(ctkDICOMDisplayedFieldGenerator); - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->AllRules) + + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->GeneratorRules) { rule->endUpdate(displayedFieldsMapSeries, displayedFieldsMapStudy, displayedFieldsMapPatient); } @@ -168,15 +200,5 @@ void ctkDICOMDisplayedFieldGenerator::setDatabase(ctkDICOMDatabase* database) d->Database = database; - foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule, d->AllRules) - { - rule->setDatabase(database); - } -} - -//------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGenerator::registerDisplayedFieldGeneratorRule(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule) -{ - Q_D(ctkDICOMDisplayedFieldGenerator); - d->AllRules.append(rule); + d->setupEnabledDisplayedFieldGeneratorRules(); } diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h index 3d190d4e22..6848133d95 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator.h @@ -51,7 +51,7 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGenerator : public QObject { Q_OBJECT public: - explicit ctkDICOMDisplayedFieldGenerator(QObject *parent = 0); + explicit ctkDICOMDisplayedFieldGenerator(QObject* parent); virtual ~ctkDICOMDisplayedFieldGenerator(); /// Set DICOM database @@ -79,9 +79,6 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGenerator : public QObject QMap > &displayedFieldsMapStudy, QMap > &displayedFieldsMapPatient); - /// Register new displayed field generator rule - void registerDisplayedFieldGeneratorRule(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule); - protected: QScopedPointer d_ptr; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h index 4afd56171f..e120ae95bf 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorAbstractRule.h @@ -44,6 +44,12 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorAbstractRule public: virtual ~ctkDICOMDisplayedFieldGeneratorAbstractRule(){} + /// Get name of rule + virtual QString name()const = 0; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + virtual ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() = 0; + /// Generate displayed fields for a certain instance based on its cached tags /// Each rule plugin has the chance to fill any field in the series, study, and patient fields. /// The way these generated fields will be used is defined by \sa mergeDisplayedFieldsForInstance diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp index 4b72ea8976..43b2fe4354 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.cpp @@ -23,6 +23,18 @@ // dcmtk includes #include "dcmtk/dcmdata/dcvrpn.h" +//------------------------------------------------------------------------------ +QString ctkDICOMDisplayedFieldGeneratorDefaultRule::name()const +{ + return "Default"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorDefaultRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorDefaultRule(); +} + //------------------------------------------------------------------------------ QStringList ctkDICOMDisplayedFieldGeneratorDefaultRule::getRequiredDICOMTags() { diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.h index 3df4c0effa..13596f579c 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorDefaultRule.h @@ -34,6 +34,12 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorDefaultRule : public ctkDICOMDisplayedFieldGeneratorAbstractRule { public: + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; + /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.cpp index a1849e76bf..8af075c99c 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.cpp @@ -33,6 +33,18 @@ ctkDICOMDisplayedFieldGeneratorLastStudyDateRule::ctkDICOMDisplayedFieldGenerato { } +//------------------------------------------------------------------------------ +QString ctkDICOMDisplayedFieldGeneratorLastStudyDateRule::name()const +{ + return "LastStudyDate"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorLastStudyDateRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorLastStudyDateRule(); +} + //------------------------------------------------------------------------------ QStringList ctkDICOMDisplayedFieldGeneratorLastStudyDateRule::getRequiredDICOMTags() { diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h index 7f2ba61169..ad38e6b57a 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h @@ -36,6 +36,12 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorLastStudyDateRule : p /// Constructor explicit ctkDICOMDisplayedFieldGeneratorLastStudyDateRule(); + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; + /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.cpp similarity index 79% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.cpp rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.cpp index e1560eb585..554895b51a 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.cpp @@ -18,7 +18,7 @@ =========================================================================*/ -#include "ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h" +#include "ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h" // ctkDICOM includes #include "ctkDICOMDatabase.h" @@ -29,12 +29,24 @@ #include //------------------------------------------------------------------------------ -ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies() +ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule() { } //------------------------------------------------------------------------------ -QStringList ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::getRequiredDICOMTags() +QString ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::name()const +{ + return "PatientNumberOfStudies"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule(); +} + +//------------------------------------------------------------------------------ +QStringList ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::getRequiredDICOMTags() { QStringList requiredTags; @@ -50,7 +62,7 @@ QStringList ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::getRequiredDI } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::getDisplayedFieldsForInstance( +void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::getDisplayedFieldsForInstance( const QMap &cachedTagsForInstance, QMap &displayedFieldsForCurrentSeries, QMap &displayedFieldsForCurrentStudy, QMap &displayedFieldsForCurrentPatient ) { @@ -62,13 +74,13 @@ void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::getDisplayedFieldsFo } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::startUpdate() +void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::startUpdate() { this->UpdatedPatientCompositeIDs.clear(); } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies::endUpdate( +void ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule::endUpdate( QMap > &displayedFieldsMapSeries, QMap > &displayedFieldsMapStudy, QMap > &displayedFieldsMapPatient) diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h similarity index 85% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h index 13b7770a8a..98ac47480d 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h @@ -18,8 +18,8 @@ =========================================================================*/ -#ifndef __ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies_h -#define __ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies_h +#ifndef __ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule_h +#define __ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule_h // Qt includes #include @@ -30,11 +30,17 @@ /// \ingroup DICOM_Core /// /// Rule for generating number of studies in the patients that belong to the newly added instances -class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies : public ctkDICOMDisplayedFieldGeneratorAbstractRule +class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule : public ctkDICOMDisplayedFieldGeneratorAbstractRule { public: /// Constructor - explicit ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudies(); + explicit ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule(); + + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp index 6e9390cdeb..d394ef7b93 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.cpp @@ -28,6 +28,18 @@ ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule::ctkDICOMDispla { } +//------------------------------------------------------------------------------ +QString ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule::name()const +{ + return "RadiotherapySeriesDescription"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule(); +} + //------------------------------------------------------------------------------ QStringList ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule::getRequiredDICOMTags() { diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h index 92d2ff2416..52114ae231 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h @@ -35,6 +35,12 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDes /// Constructor explicit ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule(); + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; + /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.cpp new file mode 100644 index 0000000000..e1513c7d0b --- /dev/null +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.cpp @@ -0,0 +1,191 @@ +/*============================================================================== + + Library: CTK + + Copyright (c) Pixel Medical Inc. 2021 + + 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. + + ==============================================================================*/ + +#include "ctkDICOMDisplayedFieldGeneratorRuleFactory.h" + +#include "ctkDICOMDatabase.h" +#include "ctkDICOMDisplayedFieldGeneratorDefaultRule.h" +#include "ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule.h" +#include "ctkDICOMDisplayedFieldGeneratorLastStudyDateRule.h" +#include "ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h" +#include "ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h" +#include "ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule.h" + +// Qt includes +#include +#include +#include + +//---------------------------------------------------------------------------- +ctkDICOMDisplayedFieldGeneratorRuleFactory *ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance = nullptr; + +//---------------------------------------------------------------------------- +class ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanup +{ +public: + inline void use() { } + + ~ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanup() + { + if (ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance) + { + ctkDICOMDisplayedFieldGeneratorRuleFactory::cleanup(); + } + } +}; + +//----------------------------------------------------------------------------- +static ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanup ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanupGlobal; + +//----------------------------------------------------------------------------- +ctkDICOMDisplayedFieldGeneratorRuleFactory* ctkDICOMDisplayedFieldGeneratorRuleFactory::instance() +{ + if (!ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance) + { + ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanupGlobal.use(); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance = new ctkDICOMDisplayedFieldGeneratorRuleFactory(); + + // Pre-register commonly used rules + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorDefaultRule); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorRadiotherapySeriesDescriptionRule); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorLastStudyDateRule); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule); + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance->registerDisplayedFieldGeneratorRule( + new ctkDICOMDisplayedFieldGeneratorPatientNumberOfStudiesRule); + + } + + // Return the instance + return ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance; +} + +//----------------------------------------------------------------------------- +void ctkDICOMDisplayedFieldGeneratorRuleFactory::cleanup() +{ + if (ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance) + { + delete ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance; + ctkDICOMDisplayedFieldGeneratorRuleFactory::Instance = nullptr; + } +} + +//----------------------------------------------------------------------------- +ctkDICOMDisplayedFieldGeneratorRuleFactory::ctkDICOMDisplayedFieldGeneratorRuleFactory(QObject* parent) + : QObject(parent) +{ + this->DisplayedFieldGeneratorRules.clear(); +} + +//----------------------------------------------------------------------------- +ctkDICOMDisplayedFieldGeneratorRuleFactory::~ctkDICOMDisplayedFieldGeneratorRuleFactory() +{ + foreach(auto rule, this->DisplayedFieldGeneratorRules) + { + delete rule; + } + + this->DisplayedFieldGeneratorRules.clear(); +} + +//----------------------------------------------------------------------------- +bool ctkDICOMDisplayedFieldGeneratorRuleFactory::registerDisplayedFieldGeneratorRule(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule) +{ + // Check for null + if (!rule) + { + qCritical() << Q_FUNC_INFO << ": Invalid displayed field generator rule"; + return false; + } + if (rule->name().isEmpty()) + { + qCritical() << Q_FUNC_INFO << ": Displayed field generator rule cannot be registered with empty name"; + return false; + } + + // Check for already registered rule + foreach(auto ®isteredRule, this->DisplayedFieldGeneratorRules) + { + if (registeredRule->name() == rule->name()) + { + qWarning() << Q_FUNC_INFO << ": displayed field generator rule type " << rule->name() << " is already registered."; + return false; + } + } + + // Register the displayed field generator rule + this->DisplayedFieldGeneratorRules.append(rule); + + // Emit registered signal + emit displayedFieldGeneratorRuleRegistered(); + + return true; +} + +//--------------------------------------------------------------------------- +QList +ctkDICOMDisplayedFieldGeneratorRuleFactory::copyEnabledDisplayedFieldGeneratorRules(ctkDICOMDatabase* database) +{ + QList copiedRules; + + if (!database) + { + qCritical() << Q_FUNC_INFO << " failed: DICOM database needs to be given"; + return copiedRules; + } + + // Get names of disabled displayed field generator rules from database. + // We get the disabled rules instead of the enabled ones so that if a rule does not have an entry in the table or + // the table is missing, then the rules are treated as enabled by default. + QList disabledRuleNames; + QSqlQuery disabledDisplayedFieldGeneratorRulesQuery(database->database()); + disabledDisplayedFieldGeneratorRulesQuery.prepare("SELECT Name FROM DisplayedFieldGeneratorRules WHERE Enabled = 0;"); + if (disabledDisplayedFieldGeneratorRulesQuery.exec()) + { + while (disabledDisplayedFieldGeneratorRulesQuery.next()) + { + disabledRuleNames << disabledDisplayedFieldGeneratorRulesQuery.value(0).toString(); + } + disabledDisplayedFieldGeneratorRulesQuery.finish(); + } + + foreach(ctkDICOMDisplayedFieldGeneratorAbstractRule* registeredRule, this->DisplayedFieldGeneratorRules) + { + // If rule is explicitly enabled or there is no such information then accept it + if (!disabledRuleNames.contains(registeredRule->name())) + { + ctkDICOMDisplayedFieldGeneratorAbstractRule* clonedRule = registeredRule->clone(); + if (!clonedRule) + { + // Make sure we don't put a null pointer in the rule list + qCritical() << Q_FUNC_INFO << " failed to clone displayed field generator rule: " << registeredRule->name(); + continue; + } + copiedRules << clonedRule; + } + } + + return copiedRules; +} diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.h new file mode 100644 index 0000000000..971bca8d81 --- /dev/null +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorRuleFactory.h @@ -0,0 +1,84 @@ +/*============================================================================== + + Library: CTK + + Copyright (c) Pixel Medical Inc. 2021 + + 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. + + ==============================================================================*/ + +#ifndef __ctkDICOMDisplayedFieldGeneratorRuleFactory_h_ +#define __ctkDICOMDisplayedFieldGeneratorRuleFactory_h_ + +#include "ctkDICOMCoreExport.h" + +// Qt includes +#include +#include + +class ctkDICOMDatabase; +class ctkDICOMDisplayedFieldGeneratorAbstractRule; +class ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanup; + +/// \ingroup SlicerRt_QtModules_Segmentations +/// \class ctkDICOMDisplayedFieldGeneratorRuleFactory +/// \brief Singleton class managing displayed field generator rules +class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorRuleFactory : public QObject +{ + Q_OBJECT + +public: + /// Instance getter for the singleton class + /// \return Instance object + Q_INVOKABLE static ctkDICOMDisplayedFieldGeneratorRuleFactory* instance(); + +public: + /// Register a displayed field generator rule. The factory takes ownership of the object (caller must not delete it). + /// \return True if rule is registered successfully, false otherwise + Q_INVOKABLE bool registerDisplayedFieldGeneratorRule(ctkDICOMDisplayedFieldGeneratorAbstractRule* rule); + + /// Return the list of displayed field generator rules registered. + Q_INVOKABLE const QList& displayedFieldGeneratorRules() + { return this->DisplayedFieldGeneratorRules; } + + /// Return a list with the copies of displayed field generator rules that are enabled according to the database. + /// \param database DICOM database in which the DisplayedFieldGeneratorRules table is used to decide if a rule is + /// enabled or not. If the table itself or an entry with a particular rule name is missing then the rule is treated as enabled. + Q_INVOKABLE QList copyEnabledDisplayedFieldGeneratorRules(ctkDICOMDatabase* database); + +signals: + void displayedFieldGeneratorRuleRegistered(); + void displayedFieldGeneratorRuleUnregistered(); + +protected: + QList DisplayedFieldGeneratorRules; + +private: + /// Allows cleanup of the singleton at application exit + static void cleanup(); + +private: + ctkDICOMDisplayedFieldGeneratorRuleFactory(QObject* parent=nullptr); + ~ctkDICOMDisplayedFieldGeneratorRuleFactory() override; + + Q_DISABLE_COPY(ctkDICOMDisplayedFieldGeneratorRuleFactory); + friend class ctkDICOMDisplayedFieldGeneratorRuleFactoryCleanup; + friend class PythonQtWrapper_ctkDICOMDisplayedFieldGeneratorRuleFactory; // Allow Python wrapping without enabling direct instantiation + +private: + /// Instance of the singleton + static ctkDICOMDisplayedFieldGeneratorRuleFactory* Instance; +}; + +#endif // __ctkDICOMDisplayedFieldGeneratorRuleFactory_h_ diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.cpp similarity index 76% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.cpp rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.cpp index 69c20170dc..ca48a912fa 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.cpp @@ -18,7 +18,7 @@ =========================================================================*/ -#include "ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h" +#include "ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h" // ctkDICOM includes #include "ctkDICOMDatabase.h" @@ -29,12 +29,24 @@ #include //------------------------------------------------------------------------------ -ctkDICOMDisplayedFieldGeneratorSeriesImageCount::ctkDICOMDisplayedFieldGeneratorSeriesImageCount() +ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule() { } //------------------------------------------------------------------------------ -QStringList ctkDICOMDisplayedFieldGeneratorSeriesImageCount::getRequiredDICOMTags() +QString ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::name()const +{ + return "SeriesImageCount"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule(); +} + +//------------------------------------------------------------------------------ +QStringList ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::getRequiredDICOMTags() { QStringList requiredTags; @@ -44,7 +56,7 @@ QStringList ctkDICOMDisplayedFieldGeneratorSeriesImageCount::getRequiredDICOMTag } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorSeriesImageCount::getDisplayedFieldsForInstance( +void ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::getDisplayedFieldsForInstance( const QMap &cachedTagsForInstance, QMap &displayedFieldsForCurrentSeries, QMap &displayedFieldsForCurrentStudy, QMap &displayedFieldsForCurrentPatient ) { @@ -53,13 +65,13 @@ void ctkDICOMDisplayedFieldGeneratorSeriesImageCount::getDisplayedFieldsForInsta } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorSeriesImageCount::startUpdate() +void ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::startUpdate() { this->UpdatedSeriesInstanceUIDs.clear(); } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorSeriesImageCount::endUpdate( +void ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule::endUpdate( QMap > &displayedFieldsMapSeries, QMap > &displayedFieldsMapStudy, QMap > &displayedFieldsMapPatient) diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h similarity index 83% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h index 34f65993f2..a4628c3cfe 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCount.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule.h @@ -18,8 +18,8 @@ =========================================================================*/ -#ifndef __ctkDICOMDisplayedFieldGeneratorSeriesImageCount_h -#define __ctkDICOMDisplayedFieldGeneratorSeriesImageCount_h +#ifndef __ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule_h +#define __ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule_h // Qt includes #include @@ -30,11 +30,17 @@ /// \ingroup DICOM_Core /// /// Rule for generating number of images in the series that belong to the newly added instances -class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorSeriesImageCount : public ctkDICOMDisplayedFieldGeneratorAbstractRule +class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule : public ctkDICOMDisplayedFieldGeneratorAbstractRule { public: /// Constructor - explicit ctkDICOMDisplayedFieldGeneratorSeriesImageCount(); + explicit ctkDICOMDisplayedFieldGeneratorSeriesImageCountRule(); + + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.cpp b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.cpp similarity index 75% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.cpp rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.cpp index 18a4104f03..1aa2f74fa1 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.cpp +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.cpp @@ -18,7 +18,7 @@ =========================================================================*/ -#include "ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h" +#include "ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h" // ctkDICOM includes #include "ctkDICOMDatabase.h" @@ -29,12 +29,24 @@ #include //------------------------------------------------------------------------------ -ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries() +ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule() { } //------------------------------------------------------------------------------ -QStringList ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::getRequiredDICOMTags() +QString ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::name()const +{ + return "StudyNumberOfSeries"; +} + +//------------------------------------------------------------------------------ +ctkDICOMDisplayedFieldGeneratorAbstractRule* ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::clone() +{ + return new ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule(); +} + +//------------------------------------------------------------------------------ +QStringList ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::getRequiredDICOMTags() { QStringList requiredTags; @@ -44,7 +56,7 @@ QStringList ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::getRequiredDICOM } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::getDisplayedFieldsForInstance( +void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::getDisplayedFieldsForInstance( const QMap &cachedTagsForInstance, QMap &displayedFieldsForCurrentSeries, QMap &displayedFieldsForCurrentStudy, QMap &displayedFieldsForCurrentPatient ) { @@ -53,13 +65,13 @@ void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::getDisplayedFieldsForIn } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::startUpdate() +void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::startUpdate() { this->UpdatedStudyInstanceUIDs.clear(); } //------------------------------------------------------------------------------ -void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries::endUpdate( +void ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule::endUpdate( QMap > &displayedFieldsMapSeries, QMap > &displayedFieldsMapStudy, QMap > &displayedFieldsMapPatient) diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h similarity index 83% rename from Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h rename to Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h index 20bd09d304..2edde43af3 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule.h @@ -18,8 +18,8 @@ =========================================================================*/ -#ifndef __ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries_h -#define __ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries_h +#ifndef __ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule_h +#define __ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule_h // Qt includes #include @@ -30,11 +30,17 @@ /// \ingroup DICOM_Core /// /// Rule for generating number of series in the studies that belong to the newly added instances -class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries : public ctkDICOMDisplayedFieldGeneratorAbstractRule +class CTK_DICOM_CORE_EXPORT ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule : public ctkDICOMDisplayedFieldGeneratorAbstractRule { public: /// Constructor - explicit ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeries(); + explicit ctkDICOMDisplayedFieldGeneratorStudyNumberOfSeriesRule(); + + /// Get name of rule + QString name()const override; + + /// Clone displayed field generator rule. Override to return a new instance of the rule sub-class + ctkDICOMDisplayedFieldGeneratorAbstractRule* clone() override; /// Specify list of DICOM tags required by the rule. These tags will be included in the tag cache QStringList getRequiredDICOMTags() override; diff --git a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator_p.h b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator_p.h index 77a14ca1d1..1cb9d76759 100644 --- a/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator_p.h +++ b/Libs/DICOM/Core/ctkDICOMDisplayedFieldGenerator_p.h @@ -45,8 +45,18 @@ class ctkDICOMDisplayedFieldGeneratorPrivate : public QObject ctkDICOMDisplayedFieldGeneratorPrivate(ctkDICOMDisplayedFieldGenerator&); ~ctkDICOMDisplayedFieldGeneratorPrivate(); + /// Instantiate and setup displayed field generator rules that are enabled according to the database. + /// Populates \sa GeneratorRules list when update starts (\sa ctkDICOMDisplayedFieldGenerator::startUpdate). + void setupEnabledDisplayedFieldGeneratorRules(); + + /// Clear list of displayed field generator rules when update ends (\sa ctkDICOMDisplayedFieldGenerator::endUpdate). + void clearDisplayedFieldGeneratorRules(); + public: - QList AllRules; + /// List of enabled generator rules. + /// Populated on \sa ctkDICOMDisplayedFieldGenerator::startUpdate and cleared on \sa ctkDICOMDisplayedFieldGenerator::endUpdate + QList GeneratorRules; + ctkDICOMDatabase* Database; QMap EmptyFieldNamesPatients;