Skip to content

Commit

Permalink
ENH: Add server nodes widget for visual dicom browser
Browse files Browse the repository at this point in the history
  • Loading branch information
Punzo committed Oct 4, 2023
1 parent b0f8539 commit 951ee27
Show file tree
Hide file tree
Showing 25 changed files with 2,216 additions and 71 deletions.
3 changes: 3 additions & 0 deletions Libs/DICOM/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ set(KIT_SRCS
ctkDICOMItem.h
ctkDICOMDisplayedFieldGenerator.cpp
ctkDICOMDisplayedFieldGenerator.h
ctkDICOMEcho.cpp
ctkDICOMEcho.h
ctkDICOMFilterProxyModel.cpp
ctkDICOMFilterProxyModel.h
ctkDICOMIndexer.cpp
Expand Down Expand Up @@ -79,6 +81,7 @@ set(KIT_MOC_SRCS
ctkDICOMDisplayedFieldGenerator.h
ctkDICOMDisplayedFieldGenerator_p.h
ctkDICOMDisplayedFieldGeneratorRuleFactory.h
ctkDICOMEcho.h
ctkDICOMIndexer.h
ctkDICOMIndexer_p.h
ctkDICOMFilterProxyModel.h
Expand Down
261 changes: 261 additions & 0 deletions Libs/DICOM/Core/ctkDICOMEcho.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
/*=========================================================================
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 <QDebug>
#include <QSettings>
#include <QString>
#include <QStringList>

// ctkDICOMCore includes
#include "ctkDICOMEcho.h"
#include "ctkLogger.h"

// DCMTK includes
#include <dcmtk/dcmnet/scu.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmdata/dcdeftag.h>
#include <dcmtk/dcmdata/dcdatset.h>
#include <dcmtk/oflog/oflog.h>
#include <dcmtk/ofstd/ofcond.h>
#include <dcmtk/ofstd/ofstring.h>
#include <dcmtk/ofstd/oflist.h>
#include <dcmtk/ofstd/ofstd.h> /* for class OFStandard */
#include <dcmtk/dcmdata/dcddirif.h> /* for class DicomDirInterface */

static ctkLogger logger ( "org.commontk.dicom.DICOMEcho" );

//------------------------------------------------------------------------------
class ctkDICOMEchoPrivate
{
public:
ctkDICOMEchoPrivate();
~ctkDICOMEchoPrivate();

QString ConnectionName;
QString CallingAETitle;
QString CalledAETitle;
QString Host;
int Port;
DcmSCU SCU;
};

//------------------------------------------------------------------------------
// ctkDICOMEchoPrivate methods

//------------------------------------------------------------------------------
ctkDICOMEchoPrivate::ctkDICOMEchoPrivate()
{
this->Port = 0;

this->SCU.setACSETimeout(3);
this->SCU.setConnectionTimeout(3);
}

//------------------------------------------------------------------------------
ctkDICOMEchoPrivate::~ctkDICOMEchoPrivate()
{
}

//------------------------------------------------------------------------------
// ctkDICOMEcho methods

//------------------------------------------------------------------------------
ctkDICOMEcho::ctkDICOMEcho(QObject* parentObject)
: QObject(parentObject)
, d_ptr(new ctkDICOMEchoPrivate)
{
Q_D(ctkDICOMEcho);

d->SCU.setVerbosePCMode(false);
d->SCU.setProgressNotificationMode(false);

QSettings settings;
this->setDCMTKLogLevel(ctkErrorLogLevel::logLevelFromString(settings.value("CTKLogging/Level").toString()));
}

//------------------------------------------------------------------------------
ctkDICOMEcho::~ctkDICOMEcho()
{
}

//-----------------------------------------------------------------------------
void ctkDICOMEcho::setDCMTKLogLevel(const ctkErrorLogLevel::LogLevel& level)
{
OFLogger::LogLevel dcmtkLogLevel = OFLogger::OFF_LOG_LEVEL;
if (level == ctkErrorLogLevel::LogLevel::Fatal)
{
dcmtkLogLevel = OFLogger::FATAL_LOG_LEVEL;
}
else if (level == ctkErrorLogLevel::LogLevel::Critical ||
level == ctkErrorLogLevel::LogLevel::Error)
{
dcmtkLogLevel = OFLogger::ERROR_LOG_LEVEL;
}
else if (level == ctkErrorLogLevel::LogLevel::Warning)
{
dcmtkLogLevel = OFLogger::WARN_LOG_LEVEL;
}
else if (level == ctkErrorLogLevel::LogLevel::Info)
{
dcmtkLogLevel = OFLogger::INFO_LOG_LEVEL;
}
else if (level == ctkErrorLogLevel::LogLevel::Debug)
{
dcmtkLogLevel = OFLogger::DEBUG_LOG_LEVEL;
}
else if (level == ctkErrorLogLevel::LogLevel::Trace ||
level == ctkErrorLogLevel::LogLevel::Status)
{
dcmtkLogLevel = OFLogger::TRACE_LOG_LEVEL;
}

OFLog::configure(dcmtkLogLevel);
}

//-----------------------------------------------------------------------------
ctkErrorLogLevel::LogLevel ctkDICOMEcho::DCMTKLogLevel() const
{
return logger.logLevel();
}

/// Set methods for connectivity
//------------------------------------------------------------------------------
void ctkDICOMEcho::setConnectionName(const QString& connectionName)
{
Q_D(ctkDICOMEcho);
d->ConnectionName = connectionName;
}

//------------------------------------------------------------------------------
QString ctkDICOMEcho::connectionName() const
{
Q_D(const ctkDICOMEcho);
return d->ConnectionName;
}

//------------------------------------------------------------------------------
void ctkDICOMEcho::setCallingAETitle(const QString& callingAETitle)
{
Q_D(ctkDICOMEcho);
d->CallingAETitle = callingAETitle;
}

//------------------------------------------------------------------------------
QString ctkDICOMEcho::callingAETitle() const
{
Q_D(const ctkDICOMEcho);
return d->CallingAETitle;
}

//------------------------------------------------------------------------------
void ctkDICOMEcho::setCalledAETitle(const QString& calledAETitle)
{
Q_D(ctkDICOMEcho);
d->CalledAETitle = calledAETitle;
}

//------------------------------------------------------------------------------
QString ctkDICOMEcho::calledAETitle()const
{
Q_D(const ctkDICOMEcho);
return d->CalledAETitle;
}

//------------------------------------------------------------------------------
void ctkDICOMEcho::setHost(const QString& host)
{
Q_D(ctkDICOMEcho);
d->Host = host;
}

//------------------------------------------------------------------------------
QString ctkDICOMEcho::host() const
{
Q_D(const ctkDICOMEcho);
return d->Host;
}

//------------------------------------------------------------------------------
void ctkDICOMEcho::setPort (int port)
{
Q_D(ctkDICOMEcho);
d->Port = port;
}

//------------------------------------------------------------------------------
int ctkDICOMEcho::port()const
{
Q_D(const ctkDICOMEcho);
return d->Port;
}

//-----------------------------------------------------------------------------
void ctkDICOMEcho::setConnectionTimeout(const int timeout)
{
Q_D(ctkDICOMEcho);
d->SCU.setACSETimeout(timeout);
d->SCU.setConnectionTimeout(timeout);
}

//-----------------------------------------------------------------------------
int ctkDICOMEcho::connectionTimeout()
{
Q_D(const ctkDICOMEcho);
return d->SCU.getConnectionTimeout();
}

//------------------------------------------------------------------------------
bool ctkDICOMEcho::echo()
{
Q_D(ctkDICOMEcho);

d->SCU.setAETitle(OFString(this->callingAETitle().toStdString().c_str()));
d->SCU.setPeerAETitle(OFString(this->calledAETitle().toStdString().c_str()));
d->SCU.setPeerHostName(OFString(this->host().toStdString().c_str()));
d->SCU.setPeerPort(this->port());

logger.debug("Setting Transfer Syntaxes");

OFList<OFString> transferSyntaxes;
transferSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
transferSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);

d->SCU.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, transferSyntaxes);
if (!d->SCU.initNetwork().good())
{
logger.error("Error initializing the network");
return false;
}
logger.debug("Negotiating Association");

OFCondition result = d->SCU.negotiateAssociation();
if (result.bad())
{
logger.error("Error negotiating the association: " + QString(result.text()));
return false;
}

d->SCU.releaseAssociation();

return true;
}
93 changes: 93 additions & 0 deletions Libs/DICOM/Core/ctkDICOMEcho.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*=========================================================================
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.
=========================================================================*/

#ifndef __ctkDICOMEcho_h
#define __ctkDICOMEcho_h

// Qt includes
#include <QObject>
#include <QMap>
#include <QString>

// CTK includes
#include <ctkPimpl.h>

// ctkDICOMCore includes
#include "ctkDICOMCoreExport.h"
#include "ctkErrorLogLevel.h"

class ctkDICOMEchoPrivate;
class ctkDICOMTaskResults;

/// \ingroup DICOM_Core
class CTK_DICOM_CORE_EXPORT ctkDICOMEcho : public QObject
{
Q_OBJECT
Q_PROPERTY(QString connectionName READ connectionName WRITE setConnectionName);
Q_PROPERTY(QString callingAETitle READ callingAETitle WRITE setCallingAETitle);
Q_PROPERTY(QString calledAETitle READ calledAETitle WRITE setCalledAETitle);
Q_PROPERTY(QString host READ host WRITE setHost);
Q_PROPERTY(int port READ port WRITE setPort);
Q_PROPERTY(int connectionTimeout READ connectionTimeout WRITE setConnectionTimeout);

public:
explicit ctkDICOMEcho(QObject* parent = 0);
virtual ~ctkDICOMEcho();

/// Set methods for connectivity.
/// Empty by default
void setConnectionName ( const QString& connectionName );
QString connectionName()const;
/// Empty by default
void setCallingAETitle ( const QString& callingAETitle );
QString callingAETitle()const;
/// Empty by default
void setCalledAETitle ( const QString& calledAETitle );
QString calledAETitle()const;
/// Empty by default
void setHost ( const QString& host );
QString host()const;
/// Specify a port for the packet headers.
/// \a port ranges from 0 to 65535.
/// 0 by default.
void setPort ( int port );
int port()const;
/// connection timeout, default 3 sec.
void setConnectionTimeout(const int timeout);
int connectionTimeout();

/// Log level for dcmtk. Default: Error.
Q_INVOKABLE void setDCMTKLogLevel(const ctkErrorLogLevel::LogLevel& level);
Q_INVOKABLE ctkErrorLogLevel::LogLevel DCMTKLogLevel() const;

/// Echo connection.
bool echo();

protected:
QScopedPointer<ctkDICOMEchoPrivate> d_ptr;

private:
Q_DECLARE_PRIVATE(ctkDICOMEcho);
Q_DISABLE_COPY(ctkDICOMEcho);

friend class ctkDICOMEchoSCUPrivate; // for access to EchoResponseHandled
};

#endif
1 change: 1 addition & 0 deletions Libs/DICOM/Core/ctkDICOMRetrieve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ ctkDICOMRetrievePrivate::ctkDICOMRetrievePrivate(ctkDICOMRetrieve& obj)

this->SCU.setACSETimeout(3);
this->SCU.setConnectionTimeout(3);
this->SCU.setStorageDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString().c_str());
}

//------------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 951ee27

Please sign in to comment.