Refactor Network Module and add C-GET protocol.

This commit is contained in:
sunwen
2022-10-21 15:57:01 +08:00
parent f575691a60
commit 6e1dfb868e
24 changed files with 785 additions and 578 deletions

View File

@@ -1,4 +1,4 @@
#include "dicomviewerhelper.h"
#include "dicomviewerhelper.h"
#include <qDebug>
#include <QFile>
#include <QDir>
@@ -123,6 +123,7 @@ bool DicomViewerProductCfg::pacsInfo(QList<host>& info)
h.ae = (obj.find("ae").value().toString());
h.ip = (obj.find("ip").value().toString());
h.port = (obj.find("port").value().toString());
h.protocol = (obj.find("protocol").value().toInt());
info.push_back(h);
beg++;
}
@@ -145,6 +146,7 @@ bool DicomViewerProductCfg::setPacsInfo(QList<host>& info)
o["ae"] = beg->ae;
o["ip"] = beg->ip;
o["port"] = beg->port;
o["protocol"] = beg->protocol;
arr.append(o);
beg++;
}

View File

@@ -1,4 +1,4 @@
#ifndef _DICOM_VIEWER_HELPER_H_
#ifndef _DICOM_VIEWER_HELPER_H_
#define _DICOM_VIEWER_HELPER_H_
#include <QString>
@@ -13,6 +13,7 @@ struct host {
QString ae;
QString ip;
QString port;
unsigned short protocol = 0; //0:C-Move,1:C-Get
};

View File

@@ -0,0 +1,97 @@
#include "GetWorker.h"
#include "dcmtk/dcmnet/scu.h"
GetWorker::GetWorker(QObject* aParent)
: QObject(aParent)
, mScu(nullptr)
{
}
void GetWorker::setOutputDirectory(const QString& outputDirectory)
{
mOutputDirPath = outputDirectory;
}
void GetWorker::setPacsInfo(const std::string& peerIP, unsigned short peerPort, const std::string& peerTitle, const std::string& ourTitle, unsigned short ourPort)
{
mPeerIP = peerIP;
mPeerPort = peerPort;
mPeerTitle = peerTitle;
mOurPort = ourPort;
mOurTitle = ourTitle;
}
bool GetWorker::initDcmSCU()
{
mScu = new DcmSCU();
mScu->setAETitle(mOurTitle);
mScu->setPeerHostName(mPeerIP);
mScu->setPeerPort(OFstatic_cast(Uint16, mPeerPort));
mScu->setPeerAETitle(mPeerTitle);
OFList<OFString> syntaxes;
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
mScu->addPresentationContext(UID_CTImageStorage, syntaxes);
mScu->addPresentationContext(UID_MRImageStorage, syntaxes);
OFCondition cond = mScu->initNetwork();
if (cond.bad())
{
return false;
}
cond = mScu->negotiateAssociation();
if (cond.bad())
{
return false;
}
return true;
}
void GetWorker::getBySeriesUID(const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& aDicomType)
{
qDebug(aDicomType.toLatin1());
if (!initDcmSCU())
{
mScu->abortAssociation();
emit notifyGetDone(1, "");
delete mScu;
mScu = nullptr;
return;
}
mScu->setStorageDir(mOutputDirPath.toStdString());
T_ASC_PresentationContextID pcid;
if(aDicomType.toLower() == "mr")
{
pcid = mScu->findPresentationContextID(UID_MRImageStorage,"");
}
else
{
pcid = mScu->findPresentationContextID(UID_CTImageStorage,"");
}
OFList<RetrieveResponse*> responses;
DcmDataset dataset;
dataset.putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"STUDY");
dataset.putAndInsertOFStringArray(DCM_StudyInstanceUID,studyInstanceUID.toStdString());
dataset.putAndInsertOFStringArray(DCM_SeriesInstanceUID,seriesInstanceUID.toStdString());
OFCondition cond = mScu->sendCGETRequest(pcid, &dataset, &responses);
if(responses.begin() != responses.end() && (*responses.begin())->m_numberOfCompletedSubops > 0)
{
emit notifyGetDone(0,mOutputDirPath);
}
if (cond.bad()|| cond != EC_Normal)
{
mScu->closeAssociation(DCMSCU_ABORT_ASSOCIATION);
}
else
{
mScu->releaseAssociation();
}
delete mScu;
mScu = nullptr;
}

View File

@@ -0,0 +1,33 @@
#ifndef GETWORKER_H
#define GETWORKER_H
#include <QObject>
class DcmSCU;
class GetWorker : public QObject
{
Q_OBJECT
public:
GetWorker(QObject* aParent);
void setOutputDirectory(const QString& outputDir);
void setPacsInfo(const std::string& peerIP, unsigned short peerPort, const std::string& peerTitle, const std::string& ourTitle, unsigned short ourPort);
Q_INVOKABLE void getBySeriesUID(const QString& studyInstanceUID, const QString& seriesInstanceUID, const QString& aDicomType);
signals:
void notifyGetDone(int, QString aDirPath);
private:
bool initDcmSCU();
private:
DcmSCU* mScu;
QString mOutputDirPath;
std::string mPeerTitle;
std::string mPeerIP;
std::string mOurTitle;
unsigned short mPeerPort;
unsigned short mOurPort;
};
#endif // GETWORKER_H

View File

@@ -0,0 +1,12 @@
#include "MoveStoreScp.h"
MoveStoreScp::MoveStoreScp()
: DcmStorageSCP()
{
}
bool MoveStoreScp::stopAfterCurrentAssociation()
{
return true;
}

View File

@@ -0,0 +1,13 @@
#ifndef MOVESTORESCP_H
#define MOVESTORESCP_H
#include "dcmtk/dcmnet/dstorscp.h"
class MoveStoreScp : public DcmStorageSCP
{
public:
MoveStoreScp();
bool stopAfterCurrentAssociation();
};
#endif // MOVESTORESCP_H

View File

@@ -0,0 +1,41 @@
#include "MoveStoreThread.h"
#include "MoveStoreScp.h"
MoveStoreThread::MoveStoreThread(const std::string aAETitle, unsigned short aPort, QObject* aParent)
: QThread(aParent)
, mAETitle(aAETitle)
, mPort(aPort)
{
}
MoveStoreThread::~MoveStoreThread()
{
}
void MoveStoreThread::run()
{
MoveStoreScp scp;
scp.setAETitle(mAETitle);
scp.setPort(mPort);
scp.setVerbosePCMode(false);
scp.setOutputDirectory(mOutputPath);
OFList<OFString> syntaxes;
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
scp.addPresentationContext(UID_CTImageStorage,syntaxes);
scp.addPresentationContext(UID_MRImageStorage,syntaxes);
scp.listen();
exit(0);
}
void MoveStoreThread::setScpConfig(const std::string aAETitle, unsigned short aPort)
{
mAETitle = aAETitle;
mPort = aPort;
}
void MoveStoreThread::setOutputPath(const std::string& aOutputPath)
{
mOutputPath = aOutputPath;
}

View File

@@ -0,0 +1,23 @@
#ifndef MOVESTORETHREAD_H
#define MOVESTORETHREAD_H
#include <QThread>
class MoveStoreScp;
class MoveStoreThread : public QThread
{
public:
MoveStoreThread(const std::string aAETitle, unsigned short aPort, QObject* aParent = nullptr);
~MoveStoreThread();
void run();
void setScpConfig(const std::string aAETitle, unsigned short aPort);
void setOutputPath(const std::string& aOutputPath);
private:
std::string mAETitle;
unsigned short mPort;
std::string mOutputPath;
};
#endif // MOVESTORETHREAD_H

View File

@@ -1,26 +0,0 @@
#include "callbackhelper.h"
#include "dcmtk/dcmdata/dcdatset.h"
CallbackHelper::CallbackHelper(QObject *parent)
: QObject(parent)
{
}
CallbackHelper::~CallbackHelper()
{
}
void CallbackHelper::foundResult(int index, DcmDataset *response)
{
emit sig_foundResult(index, response);
}
void CallbackHelper::moveProgress(int progress, int total)
{
emit sig_moveProgress(progress, total);
}
void CallbackHelper::moveStoreProgress(int code, std::string filename)
{
emit sig_moveStoreProgress(code, filename);
}

View File

@@ -1,30 +0,0 @@
#ifndef _CALLBACKHELPER_H_
#define _CALLBACKHELPER_H_
#include <QObject>
class DcmDataset;
// A helper class which connect callback and uppper Qt application through signal/slot
class CallbackHelper : public QObject
{
Q_OBJECT
public:
explicit CallbackHelper(QObject *parent = Q_NULLPTR);
~CallbackHelper();
void foundResult(int index, DcmDataset *response);
void moveProgress(int progress, int total);
void moveStoreProgress(int code, std::string filename);
signals:
void sig_foundResult(int index, DcmDataset *response);
void sig_moveProgress(int progress, int total);
void sig_moveStoreProgress(int code, std::string filename);
};
#endif // !_CALLBACKHELPER_H_

View File

@@ -1,26 +0,0 @@
#include "cfindcallback.h"
CFindCallback::CFindCallback()
: dcm_cfind_callback()
, CFindCallbackHelper(nullptr)
{
}
CFindCallback::~CFindCallback()
{
}
void CFindCallback::setHelper(CallbackHelper *helper)
{
CFindCallbackHelper = helper;
}
void CFindCallback::callback(T_DIMSE_C_FindRQ *request, int &responseCount, T_DIMSE_C_FindRSP *rsp, DcmDataset *responseIdentifiers)
{
if (CFindCallbackHelper != nullptr)
{
//std::string name;
//responseIdentifiers->findAndGetOFString(DCM_PatientName, name);
CFindCallbackHelper->foundResult(responseCount, responseIdentifiers);
}
}

View File

@@ -1,21 +0,0 @@
#ifndef _CFIND_CALLBACK_H_
#define _CFIND_CALLBACK_H_
#include "dcm_find.h"
#include "callbackhelper.h"
class CFindCallback : public dcm_cfind_callback
{
public:
CFindCallback();
virtual ~CFindCallback();
virtual void callback(T_DIMSE_C_FindRQ *request, int &responseCount, T_DIMSE_C_FindRSP *rsp, DcmDataset *responseIndentifiers);
void setHelper(CallbackHelper *h);
private:
CallbackHelper *CFindCallbackHelper;
};
#endif

View File

@@ -1,26 +0,0 @@
#include "cmovecallback.h"
CMoveCallback::CMoveCallback()
: dcm_cmove_callback()
, CMoveCallbackHelper(nullptr)
{
}
CMoveCallback::~CMoveCallback()
{
}
void CMoveCallback::setHelper(CallbackHelper *helper)
{
CMoveCallbackHelper = helper;
}
void CMoveCallback::callback(T_DIMSE_C_MoveRQ *request, int responseCount, T_DIMSE_C_MoveRSP *response)
{
if (CMoveCallbackHelper != nullptr)
{
CMoveCallbackHelper ->moveProgress(response->NumberOfCompletedSubOperations, response->NumberOfCompletedSubOperations + response->NumberOfRemainingSubOperations);
}
}

View File

@@ -1,24 +0,0 @@
#ifndef _CMOVE_CALLBACK_H_
#define _CMOVE_CALLBACK_H_
#include "dcm_move.h"
#include "callbackhelper.h"
class CMoveCallback : public dcm_cmove_callback
{
public:
CMoveCallback();
~CMoveCallback();
virtual void callback(T_DIMSE_C_MoveRQ *request, int responseCount, T_DIMSE_C_MoveRSP *response);
void setHelper(CallbackHelper *helper);
private:
CallbackHelper *CMoveCallbackHelper;
};
#endif // !_CMOVE_CALLBACK_H_

View File

@@ -1,45 +0,0 @@
#include "cmovestorescpcallback.h"
CMoveStoreSCPCallback::CMoveStoreSCPCallback(std::string outDirectory)
: dcm_cmove_storescp_callback()
, CMoveStoreScpCallbackHelper(nullptr)
{
outDirectory_ = outDirectory;
}
CMoveStoreSCPCallback::~CMoveStoreSCPCallback()
{
}
void CMoveStoreSCPCallback::setHelper(CallbackHelper *helper)
{
CMoveStoreScpCallbackHelper = helper;
}
void CMoveStoreSCPCallback::callback(T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ *request, char *imageFileName, DcmDataset **imageDataSet, T_DIMSE_C_StoreRSP *response, DcmDataset **statusDetail)
{
if (progress->state == DIMSE_StoreEnd)
{
if (imageDataSet != nullptr && *imageDataSet != nullptr)
{
std::string ofname;
OFStandard::combineDirAndFilename(ofname, outDirectory_, imageFile_, true); // use base class's imageFile_
E_TransferSyntax xfer = (*imageDataSet)->getOriginalXfer();
OFCondition cond = dcmff_->saveFile(ofname.c_str(), xfer, EET_ExplicitLength, EGL_recalcGL, EPD_withoutPadding, 0, 0, EWM_fileformat);
if (cond.bad())
{
OFStandard::deleteFile(ofname);
if (CMoveStoreScpCallbackHelper != nullptr)
CMoveStoreScpCallbackHelper->moveStoreProgress(1, imageFile_);
}
else
{
if (CMoveStoreScpCallbackHelper != nullptr)
CMoveStoreScpCallbackHelper->moveStoreProgress(0, imageFile_);
}
}
}
}

View File

@@ -1,27 +0,0 @@
#ifndef _CMOVE_STORESCP_CALLBACK_H_
#define _CMOVE_STORESCP_CALLBACK_H_
#include "dcm_move.h"
#include "callbackhelper.h"
class CMoveStoreSCPCallback : public dcm_cmove_storescp_callback
{
public:
CMoveStoreSCPCallback(std::string outDirectory);
~CMoveStoreSCPCallback();
virtual void callback(T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ *request, char *imageFileName, DcmDataset **imageDataSet, T_DIMSE_C_StoreRSP *response, DcmDataset **statusDetail);
void setHelper(CallbackHelper *helper);
private:
CallbackHelper *CMoveStoreScpCallbackHelper;
std::string outDirectory_;
};
#endif // !_CMOVE_STORESCP_CALLBACK_H_

View File

@@ -1,54 +1,111 @@
#include "moveworker.h"
#include "MoveStoreThread.h"
#include "dcmtk/dcmnet/scu.h"
MoveWorker::MoveWorker(const QString& peerIP, unsigned long long peerPort, const QString& peerTitle, unsigned long long ourPort, const QString& ourTitle, const QString& outputDirectory, QObject *parent)
MoveWorker::MoveWorker(const std::string& peerIP, unsigned long long peerPort, const std::string& peerTitle, unsigned long long ourPort, const std::string& ourTitle, const QString& outputDirectory, QObject *parent)
: QObject(parent)
, m_pCallbackHelper(nullptr)
, mMoveStoreThread(new MoveStoreThread(ourTitle, static_cast<unsigned short>(ourPort),this))
, mScu(nullptr)
, mIsSendMoveMsgSucessed(false)
{
m_strPeerIP_ = peerIP;
m_ulPeerPort_ = peerPort;
m_strPeerTitle_ = peerTitle;
m_ulOurPort_ = ourPort;
m_strOurTitle_ = ourTitle;
m_strOutputDirectory_ = outputDirectory;
mStrPeerIP = peerIP;
mUlPeerPort = peerPort;
mStrPeerTitle = peerTitle;
mUlOurPort = ourPort;
mStrOurTitle = ourTitle;
mStrOutputDirectory = outputDirectory;
connect(mMoveStoreThread,&QThread::finished,this,&MoveWorker::onMoveDone);
}
void MoveWorker::setOutputDirectory(const QString& outputDirectory)
{
m_strOutputDirectory_ = outputDirectory;
mStrOutputDirectory = outputDirectory;
mMoveStoreThread->setOutputPath(mStrOutputDirectory.toStdString());
}
void MoveWorker::setPacsInfo(const std::string& peerIP, unsigned long peerPort, const std::string& peerTitle, const std::string& ourTitle, unsigned long ourPort)
{
mStrPeerIP = peerIP;
mUlPeerPort = peerPort;
mStrPeerTitle = peerTitle;
mUlOurPort = ourPort;
mStrOurTitle = ourTitle;
}
bool MoveWorker::initDcmSCU()
{
mScu = new DcmSCU();
mScu->setAETitle(mStrOurTitle);
mScu->setPeerHostName(mStrPeerIP);
mScu->setPeerPort(OFstatic_cast(Uint16, mUlPeerPort));
mScu->setPeerAETitle(mStrPeerTitle);
OFList<OFString> syntaxes;
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
mScu->addPresentationContext(UID_MOVEPatientRootQueryRetrieveInformationModel, syntaxes);
OFCondition cond = mScu->initNetwork();
if (cond.bad())
{
return false;
}
cond = mScu->negotiateAssociation();
if (cond.bad())
{
return false;
}
return true;
}
void MoveWorker::moveBySeriesUID(const QString& studyInstanceUID, const QString& seriesInstanceUID)
{
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long long ullPeerPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
unsigned long long ullOurPort = m_ulOurPort_;
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cmove *cmove = new dcm_cmove(strPeerIP.c_str(), ullPeerPort, strPeerTitle.c_str(), ullOurPort, strOurTitle.c_str());
if (!initDcmSCU())
{
mScu->abortAssociation();
emit notifyMoveDone(1, "");
delete mScu;
mScu = nullptr;
return;
}
mMoveStoreThread->setScpConfig(mStrOurTitle,static_cast<unsigned short>(mUlOurPort));
mMoveStoreThread->start();
T_ASC_PresentationContextID pcid = mScu->findPresentationContextID(UID_MOVEPatientRootQueryRetrieveInformationModel,"");
OFList<RetrieveResponse*> responses;
DcmDataset dataset;
std::string strStudyInstanceUID = studyInstanceUID.toStdString();
std::string strSeriesInstanceUID = seriesInstanceUID.toStdString();
dataset.putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"STUDY");
dataset.putAndInsertOFStringArray(DCM_StudyInstanceUID,strStudyInstanceUID);
dataset.putAndInsertOFStringArray(DCM_SeriesInstanceUID,strSeriesInstanceUID);
OFCondition cond = mScu->sendMOVERequest(pcid,mStrOurTitle, &dataset, &responses);
CMoveCallback *moveCallback = new CMoveCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_moveProgress(int, int)), this, SLOT(onMoveProgress(int, int)), Qt::DirectConnection);
connect(m_pCallbackHelper, &CallbackHelper::sig_moveStoreProgress, [=](int i,std::string str){
onMoveStoreProgress(i, str.c_str());
});
}
moveCallback->setHelper(m_pCallbackHelper);
cmove->set_cmove_callback(moveCallback);
if(responses.begin() != responses.end() && (*responses.begin())->m_numberOfCompletedSubops > 0)
{
mIsSendMoveMsgSucessed = true;
}
else
{
mMoveStoreThread->terminate();
}
std::string strOutputDirectory = m_strOutputDirectory_.toStdString();
CMoveStoreSCPCallback *moveStoreCallback = new CMoveStoreSCPCallback(strOutputDirectory);
moveStoreCallback->setHelper(m_pCallbackHelper);
cmove->set_cmove_scp_callback(moveStoreCallback);
if (cond.bad()|| cond != EC_Normal)
{
mScu->closeAssociation(DCMSCU_ABORT_ASSOCIATION);
}
else
{
mScu->releaseAssociation();
}
delete mScu;
mScu = nullptr;
std::string strStudyInstanceUID = studyInstanceUID.toStdString();
std::string strSeriesInstanceUID = seriesInstanceUID.toStdString();
int ret = cmove->move_by_series_uid(strStudyInstanceUID, strSeriesInstanceUID);
emit notifyMoveDone(ret, m_strOutputDirectory_);
}
void MoveWorker::onMoveDone()
{
if(mIsSendMoveMsgSucessed)
{
emit notifyMoveDone(0, mStrOutputDirectory);
mIsSendMoveMsgSucessed = false;
}
}
void MoveWorker::onMoveProgress(int progress, int total)
@@ -59,4 +116,4 @@ void MoveWorker::onMoveProgress(int progress, int total)
void MoveWorker::onMoveStoreProgress(int code, QString filename)
{
emit notifyMoveStoreProgress(code, filename);
}
}

View File

@@ -2,18 +2,18 @@
#define _MOVEWORKER_H_
#include <QObject>
#include "callbackhelper.h"
#include "cmovecallback.h"
#include "cmovestorescpcallback.h"
class MoveStoreThread;
class DcmSCU;
class MoveWorker : public QObject
{
Q_OBJECT
public:
explicit MoveWorker(const QString& peerIP, unsigned long long peerPort, const QString& peerTitle, unsigned long long ourPort, const QString& ourTitle, const QString& outputDirectory, QObject *parent = Q_NULLPTR);
explicit MoveWorker(const std::string& peerIP, unsigned long long peerPort, const std::string& peerTitle, unsigned long long ourPort, const std::string& ourTitle, const QString& outputDirectory, QObject *parent = Q_NULLPTR);
void setOutputDirectory(const QString& outputDir);
void setPacsInfo(const std::string& peerIP, unsigned long peerPort, const std::string& peerTitle, const std::string& ourTitle, unsigned long ourPort);
Q_INVOKABLE void moveBySeriesUID(const QString& studyInstanceUID, const QString& seriesInstanceUID);
signals:
@@ -24,15 +24,21 @@ signals:
public slots:
void onMoveProgress(int, int);
void onMoveStoreProgress(int, QString);
void onMoveDone();
private:
QString m_strPeerIP_;
unsigned long long m_ulPeerPort_;
QString m_strPeerTitle_;
unsigned long long m_ulOurPort_;
QString m_strOurTitle_;
QString m_strOutputDirectory_;
CallbackHelper* m_pCallbackHelper;
bool initDcmSCU();
private:
std::string mStrPeerIP;
unsigned long long mUlPeerPort;
std::string mStrPeerTitle;
unsigned long long mUlOurPort;
std::string mStrOurTitle;
QString mStrOutputDirectory;
MoveStoreThread* mMoveStoreThread;
DcmSCU* mScu;
bool mIsSendMoveMsgSucessed;
};

View File

@@ -1,15 +1,23 @@
#include "queryworker.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmnet/scu.h"
QueryWorker::QueryWorker(const QString& peerIP, unsigned long peerPort, const QString& peerTitle, const QString& ourTitle, QObject *parent)
: QObject(parent)
, m_pCallbackHelper(nullptr)
, m_Scu(nullptr)
, m_QueryDataSet(new DcmDataset())
{
m_strPeerIP_ = peerIP;
m_ulPeerPort_ = peerPort;
m_strPeerTitle_ = peerTitle;
m_strOurTitle_ = ourTitle;
m_iQueryLevel = 0;
initQueryDataSet();
}
QueryWorker::~QueryWorker()
{
delete m_QueryDataSet;
}
void QueryWorker::setPacsInfo(const QString& peerIP, unsigned long peerPort, const QString& peerTitle, const QString& ourTitle)
@@ -20,195 +28,166 @@ void QueryWorker::setPacsInfo(const QString& peerIP, unsigned long peerPort, con
m_strOurTitle_ = ourTitle;
}
bool QueryWorker::initDcmSCU()
{
m_Scu = new DcmSCU();
m_Scu->setAETitle(m_strOurTitle_.toStdString());
m_Scu->setPeerHostName(m_strPeerIP_.toStdString());
m_Scu->setPeerPort(OFstatic_cast(Uint16, m_ulPeerPort_));
m_Scu->setPeerAETitle(m_strPeerTitle_.toStdString());
OFList<OFString> syntaxes;
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
m_Scu->addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, syntaxes);
OFCondition cond = m_Scu->initNetwork();
if (cond.bad())
{
return false;
}
cond = m_Scu->negotiateAssociation();
if (cond.bad())
{
return false;
}
return true;
}
void QueryWorker::initQueryDataSet()
{
m_QueryDataSet->putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"STUDY");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientName,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_AccessionNumber,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientBirthDate,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientSex,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyInstanceUID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_RequestingPhysician,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_SeriesInstanceUID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_Modality,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_SeriesNumber,"");
}
void QueryWorker::executeCFind(DcmDataset* aQueryKeys)
{
if (!initDcmSCU())
{
m_Scu->abortAssociation();
emit sendFindDone(0);
delete m_Scu;
m_Scu = nullptr;
return;
}
OFList<QRResponse*> responses;
T_ASC_PresentationContextID pcid = m_Scu->findPresentationContextID(UID_FINDStudyRootQueryRetrieveInformationModel,"");
OFCondition cond = m_Scu->sendFINDRequest(pcid, aQueryKeys, &responses);
emit sendFindDone(responses.empty() ? 0 : static_cast<int>(responses.size())-1);
if (!responses.empty())
{
for(auto item : responses)
{
if(item->m_dataset == nullptr) continue;
onFoundResult(0,item->m_dataset);
}
}
if (cond == EC_Normal)
{
m_Scu->releaseAssociation();
}
else
{
m_Scu->closeAssociation(DCMSCU_ABORT_ASSOCIATION);
}
delete m_Scu;
m_Scu = nullptr;
}
void QueryWorker::queryByPatientName(const QString& patientName)
{
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_patient_name(patientName.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_iQueryLevel = 0;
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientName,patientName.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientName,"");
}
void QueryWorker::queryByPatientNameAndDate(const QString& patientName, const QString& studyStartDate, const QString& studyEndDate)
{
QString patientName_ = "*";
patientName_ += patientName;
patientName_ += "*";
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_patient_name_and_date(patientName_.toStdString(), studyStartDate.toStdString(), studyEndDate.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
initQueryDataSet();
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientName,patientName.toStdString());
QString dateQuery = studyStartDate;
if(!studyEndDate.isEmpty())
{
dateQuery += "-"+studyEndDate;
}
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,dateQuery.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientName,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,"");
}
void QueryWorker::queryByPatientID(const QString& patientID)
{
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_patient_id(patientID.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_iQueryLevel = 0;
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientID,patientID.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientID,"");
}
void QueryWorker::queryByPatientIDAndDate(const QString& patientID, const QString& studyStartDate, const QString& studyEndDate)
{
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_patient_id_and_date(patientID.toStdString(), studyStartDate.toStdString(), studyEndDate.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_iQueryLevel = 0;
initQueryDataSet();
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientID,patientID.toStdString());
QString dateQuery = studyStartDate;
if(!studyEndDate.isEmpty())
{
dateQuery += "-"+studyEndDate;
}
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,dateQuery.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_PatientID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,"");
}
void QueryWorker::queryByAccessNo(const QString& accsessionNo)
{
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_accession_no(accsessionNo.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_iQueryLevel = 0;
m_QueryDataSet->putAndInsertOFStringArray(DCM_AccessionNumber,accsessionNo.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_AccessionNumber,"");
}
void QueryWorker::queryByAccessNoAndDate(const QString& accessionNo, const QString& studyStartDate, const QString& studyEndDate)
{
m_iQueryLevel = 0;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_accession_no_and_date(accessionNo.toStdString(), studyStartDate.toStdString(), studyEndDate.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_iQueryLevel = 0;
initQueryDataSet();
m_QueryDataSet->putAndInsertOFStringArray(DCM_AccessionNumber,accessionNo.toStdString());
QString dateQuery = studyStartDate;
if(!studyEndDate.isEmpty())
{
dateQuery += "-"+studyEndDate;
}
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,dateQuery.toStdString());
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_AccessionNumber,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,"");
}
void QueryWorker::queryBySeriesUID(const QString& studyInstanceUID)
{
m_iQueryLevel = 1;
std::string strPeerIP = m_strPeerIP_.toStdString();
unsigned long ulPort = m_ulPeerPort_;
std::string strPeerTitle = m_strPeerTitle_.toStdString();
std::string strOurTitle = m_strOurTitle_.toStdString();
dcm_cfind *cfind = new dcm_cfind(strPeerIP.c_str(), ulPort, strPeerTitle.c_str(), strOurTitle.c_str());
CFindCallback *findCallback = new CFindCallback();
if (m_pCallbackHelper == nullptr)
{
m_pCallbackHelper = new CallbackHelper();
connect(m_pCallbackHelper, SIGNAL(sig_foundResult(int, DcmDataset *)), this, SLOT(onFoundResult(int, DcmDataset *)), Qt::DirectConnection);
}
findCallback->setHelper(m_pCallbackHelper);
cfind->set_find_callback(findCallback);
int ret = cfind->find_by_series_uid(studyInstanceUID.toStdString());
emit sendFindDone(ret);
delete findCallback;
delete cfind;
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyInstanceUID,studyInstanceUID.toStdString());
m_QueryDataSet->putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"SERIES");
executeCFind(m_QueryDataSet);
m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyInstanceUID,"");
m_QueryDataSet->putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"STUDY");
}
void QueryWorker::onFoundResult(int index, DcmDataset *response)
{
std::string studyDate_, patientName_, patientID_, accessionNumber_,
patientBirthDate_, patientSex_, patientAge_, studyInstanceUID_,
patientBirthDate_, patientSex_, studyInstanceUID_,
studyID_, requestingPhysician_, seriesUid_, modality_, seriesNumber_;
response->findAndGetOFString(DCM_StudyDate, studyDate_);
response->findAndGetOFString(DCM_PatientName, patientName_);
@@ -216,7 +195,6 @@ void QueryWorker::onFoundResult(int index, DcmDataset *response)
response->findAndGetOFString(DCM_AccessionNumber, accessionNumber_);
response->findAndGetOFString(DCM_PatientBirthDate, patientBirthDate_);
response->findAndGetOFString(DCM_PatientSex, patientSex_);
response->findAndGetOFString(DCM_PatientAge, patientAge_);
response->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID_);
response->findAndGetOFString(DCM_StudyID, studyID_);
response->findAndGetOFString(DCM_RequestingPhysician, requestingPhysician_);
@@ -233,7 +211,6 @@ void QueryWorker::onFoundResult(int index, DcmDataset *response)
study.accessionNumber = QString::fromStdString(accessionNumber_);
study.patientBirthDate = QString::fromStdString(patientBirthDate_);
study.patientSex = QString::fromStdString(patientSex_);
study.patientAge = QString::fromStdString(patientAge_);
study.studyInstanceUID = QString::fromStdString(studyInstanceUID_);
study.studyID = QString::fromStdString(studyID_);
study.requestingPhysician = QString::fromStdString(requestingPhysician_);
@@ -251,4 +228,4 @@ void QueryWorker::onFoundResult(int index, DcmDataset *response)
emit sendSeriesItemFound(series);
}
}
}

View File

@@ -2,12 +2,12 @@
#define _QUERYWORKER_H_
#include <QObject>
#include <QPointer>
#include "../Common/dicomviewertype.h"
#include "callbackhelper.h"
#include "cfindcallback.h"
class DcmDataset;
class DcmSCU;
class QueryWorker : public QObject
{
@@ -15,7 +15,8 @@ class QueryWorker : public QObject
public:
explicit QueryWorker(const QString& peerIP, unsigned long peerPort, const QString& peerTitle, const QString& ourTitle, QObject *parent = Q_NULLPTR);
void setPacsInfo(const QString& peerIP, unsigned long peerPort, const QString& peerTitle, const QString& ourTitle);
~QueryWorker();
void setPacsInfo(const QString& peerIP, unsigned long peerPort, const QString& peerTitle, const QString& ourTitle);
Q_INVOKABLE void queryByPatientName(const QString& patientName);
Q_INVOKABLE void queryByPatientNameAndDate(const QString& patientName, const QString& studyStartDate, const QString& studyEndDate);
Q_INVOKABLE void queryByPatientID(const QString& patientID);
@@ -32,13 +33,19 @@ signals:
public slots:
void onFoundResult(int index, DcmDataset *response);
private:
bool initDcmSCU();
void initQueryDataSet();
void executeCFind(DcmDataset* aQueryKeys);
private:
QString m_strPeerIP_;
unsigned long m_ulPeerPort_;
QString m_strPeerTitle_;
QString m_strOurTitle_;
CallbackHelper* m_pCallbackHelper;
int m_iQueryLevel; // 0 - study, 1 - series // Here, should be a better solution
DcmSCU* m_Scu;
DcmDataset* m_QueryDataSet;
};

View File

@@ -15,14 +15,13 @@
#include <QProgressBar>
#include "PACS/Dialog/promptdialog.h"
#include "PACS/Network/cfindcallback.h"
#include "PACS/Network/callbackhelper.h"
#include "PACS/Common/dicomviewerhelper.h"
#include "PACS/Common/dicomviewertype.h"
#include "PACS/Network/queryworker.h"
#include "PACS/Network/moveworker.h"
#include "PACS/Network/GetWorker.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcm_move.h"
#include "PACS/Network/cmovecallback.h"
#include "PACS/Network/cmovestorescpcallback.h"
ImportWidget::ImportWidget(QWidget *parent)
: QDialog(parent)
@@ -50,10 +49,12 @@ ImportWidget::ImportWidget(QWidget *parent)
, m_pProgressLayout(nullptr)
, m_pProgressItem(nullptr)
, m_pProgressBar(nullptr)
, m_pQueryWorkerThread(nullptr)
, m_pQueryWorker(nullptr)
, m_pMoveWorkerThread(nullptr)
, m_pMoveWorker(nullptr)
, mQueryWorkerThread(nullptr)
, mQueryWorker(nullptr)
, mMoveWorkerThread(nullptr)
, mMoveWorker(nullptr)
, mGetWorkerThread(nullptr)
, mGetWorker(nullptr)
{
qRegisterMetaType<PACSStudyInfo>("PACSStudyInfo");
qRegisterMetaType<PACSSeriesInfo>("PACSSeriesInfo");
@@ -63,32 +64,32 @@ ImportWidget::ImportWidget(QWidget *parent)
ImportWidget::~ImportWidget()
{
if (m_pQueryWorkerThread != nullptr && !m_pQueryWorkerThread->isFinished())
if (mQueryWorkerThread != nullptr && !mQueryWorkerThread->isFinished())
{
m_pQueryWorkerThread->exit();
m_pQueryWorkerThread->wait();
delete m_pQueryWorkerThread;
m_pQueryWorkerThread = nullptr;
mQueryWorkerThread->exit();
mQueryWorkerThread->wait();
delete mQueryWorkerThread;
mQueryWorkerThread = nullptr;
}
if (m_pQueryWorker != nullptr)
if (mQueryWorker != nullptr)
{
delete m_pQueryWorker;
m_pQueryWorker = nullptr;
delete mQueryWorker;
mQueryWorker = nullptr;
}
if (m_pMoveWorkerThread != nullptr && !m_pMoveWorkerThread->isFinished())
if (mMoveWorkerThread != nullptr && !mMoveWorkerThread->isFinished())
{
m_pMoveWorkerThread->exit();
m_pMoveWorkerThread->wait();
delete m_pMoveWorkerThread;
m_pMoveWorkerThread = nullptr;
mMoveWorkerThread->exit();
mMoveWorkerThread->wait();
delete mMoveWorkerThread;
mMoveWorkerThread = nullptr;
}
if (m_pMoveWorker != nullptr)
if (mMoveWorker != nullptr)
{
delete m_pMoveWorker;
m_pMoveWorker = nullptr;
delete mMoveWorker;
mMoveWorker = nullptr;
}
}
@@ -184,13 +185,15 @@ void ImportWidget::initFilterPacs()
{
m_lHosts.clear();
DicomViewerHelper::pacsInfo(m_lHosts);
QString currentText = m_pPacsComboBox->currentText();
m_pPacsComboBox->clear();
QList<host>::const_iterator itr = m_lHosts.begin();
for (; itr != m_lHosts.end(); ++itr)
for (int i = 0; i < m_lHosts.count(); ++i)
{
m_pPacsComboBox->addItem(itr->name);
m_pPacsComboBox->addItem(m_lHosts[i].name);
if(m_lHosts[i].name == currentText)
{
m_pPacsComboBox->setCurrentIndex(i);
}
}
//for each (host var in m_lHosts)
@@ -273,6 +276,7 @@ void ImportWidget::initSeries()
//m_pSeriesSelectionModel = new QItemSelectionModel;
//m_pSeriesResult->setSelectionModel(m_pSeriesSelectionModel);
m_pSeriesResult->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_pSeriesResult->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
m_pSeriesResult->verticalHeader()->setVisible(false);
m_pSeriesResult->setShowGrid(false);
m_pSeriesResult->setSelectionMode(QAbstractItemView::SingleSelection);
@@ -341,16 +345,22 @@ void ImportWidget::getNetParams(std::string& peerIP, unsigned long& peerPort, st
break;
}
}
//for each (host var in hosts)
//{
// if (var.name == m_pPacsComboBox->currentText())
// {
// peerIP = var.ip.toStdString();
// peerPort = var.port.toULong();
// peerTitle = var.ae.toStdString();
// break;
// }
//}
}
unsigned short ImportWidget::getProtocol()
{
QList<host> hosts;
DicomViewerHelper::pacsInfo(hosts);
QList<host>::ConstIterator itr = hosts.begin();
for (; itr != hosts.end(); ++itr)
{
if (itr->name == m_pPacsComboBox->currentText())
{
return itr->protocol;
}
}
return 0;
}
void ImportWidget::onQueryDone(int code)
@@ -424,16 +434,16 @@ void ImportWidget::getDateIntervalForQuery(QString& startDate, QString& endDate)
// if pacs info changed, need reset the info
void ImportWidget::query()
{
if (m_pQueryWorkerThread == nullptr)
if (mQueryWorkerThread == nullptr)
{
m_pQueryWorkerThread = new QThread;
mQueryWorkerThread = new QThread;
}
else
{
if (!m_pQueryWorkerThread->isFinished())
if (!mQueryWorkerThread->isFinished())
{
m_pQueryWorkerThread->quit();
m_pQueryWorkerThread->wait();
mQueryWorkerThread->quit();
mQueryWorkerThread->wait();
}
}
@@ -445,16 +455,16 @@ void ImportWidget::query()
return;
}
if (m_pQueryWorker == nullptr)
if (mQueryWorker == nullptr)
{
m_pQueryWorker = new QueryWorker(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
QObject::connect(m_pQueryWorker, SIGNAL(sendFindDone(int)), this, SLOT(onQueryDone(int)), Qt::QueuedConnection);
QObject::connect(m_pQueryWorker, SIGNAL(sendStudyItemFound(PACSStudyInfo)), this, SLOT(onStudyFoundResult(PACSStudyInfo)), Qt::QueuedConnection);
QObject::connect(m_pQueryWorker, SIGNAL(sendSeriesItemFound(PACSSeriesInfo)), this, SLOT(onSeriesFoundResult(PACSSeriesInfo)), Qt::QueuedConnection);
mQueryWorker = new QueryWorker(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
QObject::connect(mQueryWorker, SIGNAL(sendFindDone(int)), this, SLOT(onQueryDone(int)), Qt::QueuedConnection);
QObject::connect(mQueryWorker, SIGNAL(sendStudyItemFound(PACSStudyInfo)), this, SLOT(onStudyFoundResult(PACSStudyInfo)), Qt::QueuedConnection);
QObject::connect(mQueryWorker, SIGNAL(sendSeriesItemFound(PACSSeriesInfo)), this, SLOT(onSeriesFoundResult(PACSSeriesInfo)), Qt::QueuedConnection);
}
m_pQueryWorker->setPacsInfo(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
m_pQueryWorker->moveToThread(m_pQueryWorkerThread);
m_pQueryWorkerThread->start();
mQueryWorker->setPacsInfo(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
mQueryWorker->moveToThread(mQueryWorkerThread);
mQueryWorkerThread->start();
m_studyInfo.clear();
@@ -463,23 +473,23 @@ void ImportWidget::query()
if (m_pDicomComboBox->currentText() == "Patient ID")
{
if(m_pDateComboBox->currentText() == "All dates" || m_pDateComboBox->currentText() == "-----------")
QMetaObject::invokeMethod(m_pQueryWorker, "queryByPatientID", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
QMetaObject::invokeMethod(mQueryWorker, "queryByPatientID", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
else
QMetaObject::invokeMethod(m_pQueryWorker, "queryByPatientIDAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
QMetaObject::invokeMethod(mQueryWorker, "queryByPatientIDAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
}
else if (m_pDicomComboBox->currentText() == "Patient name")
{
if (m_pDateComboBox->currentText() == "All dates" || m_pDateComboBox->currentText() == "-----------")
QMetaObject::invokeMethod(m_pQueryWorker, "queryByPatientName", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
QMetaObject::invokeMethod(mQueryWorker, "queryByPatientName", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
else
QMetaObject::invokeMethod(m_pQueryWorker, "queryByPatientNameAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
QMetaObject::invokeMethod(mQueryWorker, "queryByPatientNameAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
}
else if (m_pDicomComboBox->currentText() == "Accession number")
{
if (m_pDateComboBox->currentText() == "All dates" || m_pDateComboBox->currentText() == "-----------")
QMetaObject::invokeMethod(m_pQueryWorker, "queryByAccessNo", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
QMetaObject::invokeMethod(mQueryWorker, "queryByAccessNo", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()));
else
QMetaObject::invokeMethod(m_pQueryWorker, "queryByAccessNoAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
QMetaObject::invokeMethod(mQueryWorker, "queryByAccessNoAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate));
}
}
@@ -556,40 +566,40 @@ void ImportWidget::onStudySelected(const QModelIndex &current)
if (row < 0)
return;
if (m_pQueryWorkerThread == nullptr)
if (mQueryWorkerThread == nullptr)
{
m_pQueryWorkerThread = new QThread;
mQueryWorkerThread = new QThread;
}
else
{
if (!m_pQueryWorkerThread->isFinished())
if (!mQueryWorkerThread->isFinished())
{
m_pQueryWorkerThread->exit();
m_pQueryWorkerThread->wait();
mQueryWorkerThread->exit();
mQueryWorkerThread->wait();
}
}
if (m_pQueryWorker == nullptr)
if (mQueryWorker == nullptr)
{
std::string peerIP, peerTitle, ourTitle;
unsigned long peerPort = 0, ourPort = 0;
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
if (peerIP.empty() || peerTitle.empty() || ourTitle.empty() || peerPort == 0 || ourPort == 0)
{
return;
}
m_pQueryWorker = new QueryWorker(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
QObject::connect(m_pQueryWorker, SIGNAL(sendFindDone(int)), this, SLOT(onQueryDone(int)), Qt::QueuedConnection);
QObject::connect(m_pQueryWorker, SIGNAL(sendStudyItemFound(PACSStudyInfo)), this, SLOT(onStudyFoundResult(PACSStudyInfo)), Qt::QueuedConnection);
QObject::connect(m_pQueryWorker, SIGNAL(sendSeriesItemFound(PACSSeriesInfo)), this, SLOT(onSeriesFoundResult(PACSSeriesInfo)), Qt::QueuedConnection);
mQueryWorker = new QueryWorker(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), QString::fromStdString(ourTitle));
QObject::connect(mQueryWorker, SIGNAL(sendFindDone(int)), this, SLOT(onQueryDone(int)), Qt::QueuedConnection);
QObject::connect(mQueryWorker, SIGNAL(sendStudyItemFound(PACSStudyInfo)), this, SLOT(onStudyFoundResult(PACSStudyInfo)), Qt::QueuedConnection);
QObject::connect(mQueryWorker, SIGNAL(sendSeriesItemFound(PACSSeriesInfo)), this, SLOT(onSeriesFoundResult(PACSSeriesInfo)), Qt::QueuedConnection);
}
m_pQueryWorker->moveToThread(m_pQueryWorkerThread);
m_pQueryWorkerThread->start();
mQueryWorker->moveToThread(mQueryWorkerThread);
mQueryWorkerThread->start();
m_seriesInfo.clear();
std::string studyInstanceUID = m_pStudyModel->index(row, 14).data().toString().toStdString();
QMetaObject::invokeMethod(m_pQueryWorker, "queryBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)));
QMetaObject::invokeMethod(mQueryWorker, "queryBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)));
}
@@ -613,67 +623,149 @@ void ImportWidget::onSeriesSelected(const QModelIndex &current)
void ImportWidget::onSeriesDoubleClicked(const QModelIndex &current)
{
int row = current.row();
if (row < 0)
return;
if(getProtocol() == 1)
{
executeCGet(current);
}
else
{
executeCMove(current);
}
}
if (currentSeriesRow != row && m_pProgressBar != nullptr)
{
m_pProgressBar->setValue(0);
currentSeriesRow = row;
}
void ImportWidget::executeCMove(const QModelIndex &current)
{
int row = current.row();
if (row < 0)
return;
if (m_pMoveWorkerThread == nullptr)
{
m_pMoveWorkerThread = new QThread;
}
else
{
if (!m_pMoveWorkerThread->isFinished())
{
m_pMoveWorkerThread->exit();
m_pMoveWorkerThread->wait();
}
}
if (currentSeriesRow != row && m_pProgressBar != nullptr)
{
m_pProgressBar->setValue(0);
currentSeriesRow = row;
}
std::string seriesNumber = m_pSeriesModel->index(row, 1).data().toString().toStdString();
std::string studyInstanceUID = m_pSeriesModel->index(row, 4).data().toString().toStdString();
std::string studyID = m_pSeriesModel->index(row, 5).data().toString().toStdString();
std::string seriesUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
std::string patientName = m_pSeriesModel->index(row, 7).data().toString().toStdString();
std::string outDirectory = DicomViewerHelper::applicationPath().toStdString();
if (mMoveWorkerThread == nullptr)
{
mMoveWorkerThread = new QThread;
}
else
{
if (!mMoveWorkerThread->isFinished())
{
mMoveWorkerThread->exit();
mMoveWorkerThread->wait();
}
}
std::string seriesNumber = m_pSeriesModel->index(row, 1).data().toString().toStdString();
std::string studyInstanceUID = m_pSeriesModel->index(row, 4).data().toString().toStdString();
std::string studyID = m_pSeriesModel->index(row, 5).data().toString().toStdString();
std::string seriesUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
std::string patientName = m_pSeriesModel->index(row, 7).data().toString().toStdString();
std::string outDirectory = DicomViewerHelper::applicationPath().toStdString();
outDirectory += "/";
outDirectory += studyInstanceUID;
outDirectory += "/";
outDirectory += seriesUID;
outDirectory += studyInstanceUID;
outDirectory += "/";
outDirectory += seriesUID;
bool mkRet = false;
QDir d(QString::fromStdString(outDirectory));
if (!d.exists())
mkRet = d.mkpath(QString::fromStdString(outDirectory));
bool mkRet = false;
QDir d(QString::fromStdString(outDirectory));
if (!d.exists())
mkRet = d.mkpath(QString::fromStdString(outDirectory));
if (m_pMoveWorker == nullptr)
{
std::string peerIP, peerTitle, ourTitle;
unsigned long peerPort = 0, ourPort = 0;
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
if (peerIP.empty() || peerTitle.empty() || ourTitle.empty() || peerPort == 0 || ourPort == 0)
{
return;
}
if (mMoveWorker == nullptr)
{
std::string peerIP, peerTitle, ourTitle;
unsigned long peerPort = 0, ourPort = 0;
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
if (peerIP.empty() || peerTitle.empty() || ourTitle.empty() || peerPort == 0 || ourPort == 0)
{
return;
}
m_pMoveWorker = new MoveWorker(QString::fromStdString(peerIP), peerPort, QString::fromStdString(peerTitle), ourPort, QString::fromStdString(ourTitle), QString::fromStdString(outDirectory));
QObject::connect(m_pMoveWorker, SIGNAL(notifyMoveDone(int, QString)), this, SLOT(moveDone(int, QString)), Qt::QueuedConnection);
QObject::connect(m_pMoveWorker, SIGNAL(notifyMoveProgress(int, int)), this, SLOT(moveProgress(int, int)), Qt::QueuedConnection);
QObject::connect(m_pMoveWorker, SIGNAL(notifyMoveStoreProgress(int, QString)), this, SLOT(moveStoreProgress(int, QString)), Qt::QueuedConnection);
}
m_pMoveWorker->setOutputDirectory(QString::fromStdString(outDirectory));
m_pMoveWorker->moveToThread(m_pQueryWorkerThread);
m_pMoveWorkerThread->start();
mMoveWorker = new MoveWorker(peerIP, peerPort, peerTitle, ourPort, ourTitle, QString::fromStdString(outDirectory));
QObject::connect(mMoveWorker, SIGNAL(notifyMoveDone(int, QString)), this, SLOT(moveDone(int, QString)), Qt::QueuedConnection);
QObject::connect(mMoveWorker, SIGNAL(notifyMoveProgress(int, int)), this, SLOT(moveProgress(int, int)), Qt::QueuedConnection);
QObject::connect(mMoveWorker, SIGNAL(notifyMoveStoreProgress(int, QString)), this, SLOT(moveStoreProgress(int, QString)), Qt::QueuedConnection);
}
std::string peerIP, peerTitle, ourTitle;
unsigned long peerPort = 0, ourPort = 0;
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
if (peerIP.empty() || peerTitle.empty() || ourTitle.empty() || peerPort == 0 || ourPort == 0)
{
return;
}
mMoveWorker->setPacsInfo(peerIP,peerPort,peerTitle,ourTitle,ourPort);
mMoveWorker->setOutputDirectory(QString::fromStdString(outDirectory));
mMoveWorker->moveToThread(mQueryWorkerThread);
mMoveWorkerThread->start();
//std::string studyInstanceUID = m_pStudyModel->index(row, 14).data().toString().toStdString();
std::string seriesInstanceUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
QMetaObject::invokeMethod(m_pMoveWorker, "moveBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)), Q_ARG(QString, QString::fromStdString(seriesInstanceUID)));
std::string seriesInstanceUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
QMetaObject::invokeMethod(mMoveWorker, "moveBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)), Q_ARG(QString, QString::fromStdString(seriesInstanceUID)));
}
void ImportWidget::executeCGet(const QModelIndex &current)
{
int row = current.row();
if (row < 0)
return;
if (currentSeriesRow != row && m_pProgressBar != nullptr)
{
m_pProgressBar->setValue(0);
currentSeriesRow = row;
}
if (mGetWorkerThread == nullptr)
{
mGetWorkerThread = new QThread;
}
else
{
if (!mGetWorkerThread->isFinished())
{
mGetWorkerThread->exit();
mGetWorkerThread->wait();
}
}
std::string seriesNumber = m_pSeriesModel->index(row, 1).data().toString().toStdString();
std::string studyInstanceUID = m_pSeriesModel->index(row, 4).data().toString().toStdString();
std::string studyID = m_pSeriesModel->index(row, 5).data().toString().toStdString();
std::string seriesUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
std::string patientName = m_pSeriesModel->index(row, 7).data().toString().toStdString();
std::string outDirectory = DicomViewerHelper::applicationPath().toStdString();
outDirectory += "/";
outDirectory += studyInstanceUID;
outDirectory += "/";
outDirectory += seriesUID;
bool mkRet = false;
QDir d(QString::fromStdString(outDirectory));
if (!d.exists())
mkRet = d.mkpath(QString::fromStdString(outDirectory));
if (mGetWorker == nullptr)
{
mGetWorker = new GetWorker(this);
QObject::connect(mGetWorker, SIGNAL(notifyGetDone(int, QString)), this, SLOT(moveDone(int, QString)), Qt::QueuedConnection);
}
std::string peerIP, peerTitle, ourTitle;
unsigned long peerPort = 0, ourPort = 0;
getNetParams(peerIP, peerPort, peerTitle, ourPort, ourTitle);
if (peerIP.empty() || peerTitle.empty() || ourTitle.empty() || peerPort == 0 || ourPort == 0)
{
return;
}
mGetWorker->setPacsInfo(peerIP,peerPort,peerTitle,ourTitle,ourPort);
mGetWorker->setOutputDirectory(QString::fromStdString(outDirectory));
mGetWorker->moveToThread(mGetWorkerThread);
mGetWorkerThread->start();
std::string seriesInstanceUID = m_pSeriesModel->index(row, 6).data().toString().toStdString();
std::string dicomType = m_pSeriesModel->index(row, 2).data().toString().toStdString();
QMetaObject::invokeMethod(mGetWorker, "getBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)), Q_ARG(QString, QString::fromStdString(seriesInstanceUID)), Q_ARG(QString, QString::fromStdString(dicomType)));
}
@@ -778,4 +870,4 @@ void ImportWidget::onTitleBarDestroyed()
{
m_pTitleBar = Q_NULLPTR;
}
}
}

View File

@@ -7,12 +7,10 @@
#include <QList>
#include <QThread>
#include "PACS/Network/queryworker.h"
#include "PACS/Network/moveworker.h"
#include "PACS/Common/dicomviewertype.h"
#include "PACS/Common/dicomviewerhelper.h"
#include "radiusprogressbar.h"
class QVBoxLayout;
class QGridLayout;
class QHBoxLayout;
@@ -29,6 +27,9 @@ class CallbackHelper;
class DcmDataset;
class QProgressBar;
class QSpacerItem;
class QueryWorker;
class MoveWorker;
class GetWorker;
class ImportWidget : public QDialog
{
@@ -78,10 +79,13 @@ private:
void initStudy();
void initSeriesHeader();
void initSeries();
void getNetParams(std::string& peerIP, unsigned long& peerPort, std::string& peerTitle, unsigned long& ourPort, std::string& ourTitle);
void getNetParams(std::string& peerIP, unsigned long& peerPort, std::string& peerTitle, unsigned long& ourPort, std::string& ourTitle);
void updateStudyView();
void updateSeriesView();
void getDateIntervalForQuery(QString& startDate, QString& endDate);
void executeCMove(const QModelIndex &current);
void executeCGet(const QModelIndex &current);
unsigned short getProtocol();
private:
QVBoxLayout *m_pMainLayout;
@@ -125,13 +129,12 @@ private:
int currentSeriesRow;
QThread* m_pQueryWorkerThread;
QueryWorker* m_pQueryWorker;
QThread* m_pMoveWorkerThread;
MoveWorker* m_pMoveWorker;
// QThread* m_pStoreWorkerThread;
// StoreWorker* m_pStoreWorker;
QThread* mQueryWorkerThread;
QueryWorker* mQueryWorker;
QThread* mMoveWorkerThread;
MoveWorker* mMoveWorker;
QThread* mGetWorkerThread;
GetWorker* mGetWorker;
private:
struct

View File

@@ -8,6 +8,7 @@
#include <QFrame>
#include <QEvent>
#include <QIcon>
#include <QMenu>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QHeaderView>
@@ -29,6 +30,8 @@ ConfigurationDialog::ConfigurationDialog(QWidget *parent)
, m_pSpacerItem(nullptr)
, m_pDelButton(nullptr)
, m_pPacsInfo(nullptr)
, m_pPacsMenu(nullptr)
, m_pRetriveProtocolMenu(nullptr)
, m_pEditWidget(nullptr)
, m_pEditLayout(nullptr)
, m_pPeerIpAddressLabel(nullptr)
@@ -120,10 +123,24 @@ void ConfigurationDialog::initUi()
m_pPacsInfo->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_pPacsInfo->verticalHeader()->setVisible(false);
m_pPacsInfo->setShowGrid(false);
m_pPacsInfo->setContextMenuPolicy(Qt::CustomContextMenu);
m_pPacsInfo->setSelectionMode(QAbstractItemView::SingleSelection);
m_pPacsInfo->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pPacsInfo->setModel(m_pPacsModel);
connect(m_pPacsInfo,&QTableView::customContextMenuRequested,this,&ConfigurationDialog::pacsMenuRequest);
m_pMainLayout->addWidget(m_pPacsInfo);
m_pPacsMenu = new QMenu(m_pPacsInfo);
m_pRetriveProtocolMenu = new QMenu(tr("Retrive Protocol"),m_pPacsMenu);
QAction* cGetAction = new QAction("C-GET",m_pRetriveProtocolMenu);
cGetAction->setCheckable(true);
connect(cGetAction,&QAction::triggered,this,&ConfigurationDialog::changeHostProtocol);
QAction* cMoveAction = new QAction("C-MOVE",m_pRetriveProtocolMenu);
cMoveAction->setCheckable(true);
connect(cMoveAction,&QAction::triggered,this,&ConfigurationDialog::changeHostProtocol);
m_pRetriveProtocolMenu->addAction(cGetAction);
m_pRetriveProtocolMenu->addAction(cMoveAction);
m_pPacsMenu->addMenu(m_pRetriveProtocolMenu);
m_pEditWidget = new QWidget(this);
m_pEditLayout = new QGridLayout(this);
@@ -197,7 +214,7 @@ void ConfigurationDialog::initSys()
connect(m_pModifyButton, SIGNAL(clicked()), this, SLOT(modify()));
connect(m_pSaveButton, SIGNAL(clicked()), this, SLOT(save()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
connect(m_pPacsInfo, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onSelected(const QModelIndex &)));
connect(m_pPacsInfo, SIGNAL(pressed(const QModelIndex &)), this, SLOT(onSelected(const QModelIndex &)));
}
void ConfigurationDialog::initHeaderInfo()
@@ -239,7 +256,7 @@ void ConfigurationDialog::initPacsInfo()
QStandardItem* port = new QStandardItem(var.port); port->setEditable(false);
QStandardItem* ae = new QStandardItem(var.ae); ae->setEditable(false);
QStandardItem* name = new QStandardItem(var.name); name->setEditable(false);
QStandardItem* protocol = new QStandardItem("C-MOVE"); protocol->setEditable(false);
QStandardItem* protocol = new QStandardItem(var.protocol == 0 ? "C-MOVE" : "C-GET"); protocol->setEditable(false);
QStandardItem* count = new QStandardItem("1"); count->setEditable(false);
QStandardItem* xfers = new QStandardItem("Explicit VR LE"); xfers->setEditable(false);
QStandardItem* cset = new QStandardItem("Default"); cset->setEditable(false);
@@ -265,7 +282,7 @@ void ConfigurationDialog::updatePacsView()
QStandardItem* port = new QStandardItem(itr->port); port->setEditable(false);
QStandardItem* ae = new QStandardItem(itr->ae); ae->setEditable(false);
QStandardItem* name = new QStandardItem(itr->name); name->setEditable(false);
QStandardItem* protocol = new QStandardItem("C-MOVE"); protocol->setEditable(false);
QStandardItem* protocol = new QStandardItem(itr->protocol == 0 ? "C-MOVE" : "C-GET"); protocol->setEditable(false);
QStandardItem* count = new QStandardItem("1"); count->setEditable(false);
QStandardItem* xfers = new QStandardItem("Explicit VR LE"); xfers->setEditable(false);
QStandardItem* cset = new QStandardItem("Default"); cset->setEditable(false);
@@ -558,3 +575,49 @@ bool ConfigurationDialog::eventFilter(QObject *obj, QEvent *event)
return QDialog::eventFilter(obj, event);
}
void ConfigurationDialog::changeHostProtocol()
{
QAction* action = qobject_cast<QAction*>(sender());
if (action != nullptr && currentRow != -1)
{
QString selectedName = m_pPacsModel->index(currentRow, 3).data().toString();
for (auto itr = m_lHostsNew.begin(); itr != m_lHostsNew.end(); ++itr)
{
if (selectedName == itr->name)
{
if (action->text() == "C-GET")
{
itr->protocol = 1;
}
else if(action->text() == "C-MOVE")
{
itr->protocol = 0;
}
updatePacsView();
DicomViewerHelper::setPacsInfo(m_lHostsNew);
emit updatePacsInfo();
return;
}
}
}
}
void ConfigurationDialog::pacsMenuRequest(QPoint pos)
{
auto index = m_pPacsInfo->indexAt(pos);
auto actions = m_pRetriveProtocolMenu->actions();
for(int i = 0; i < actions.count(); ++i)
{
if (actions.at(i)->text() == m_pPacsModel->item(index.row(),4)->text())
{
actions.at(i)->setChecked(true);
}
else
{
actions.at(i)->setChecked(false);
}
}
m_pPacsMenu->exec(QCursor::pos());
}

View File

@@ -13,6 +13,7 @@ class QLineEdit;
class QPushButton;
class QTableView;
class QFrame;
class QMenu;
class QSpacerItem;
class QStandardItemModel;
class QItemSelectionModel;
@@ -51,6 +52,8 @@ private:
void initPacsInfo();
void updatePacsView();
void clearModify();
void pacsMenuRequest(QPoint pos);
void changeHostProtocol();
private:
QVBoxLayout *m_pMainLayout;
@@ -69,6 +72,8 @@ private:
QSpacerItem *m_pSpacerItem;
QPushButton *m_pDelButton;
QTableView *m_pPacsInfo;
QMenu* m_pPacsMenu;
QMenu* m_pRetriveProtocolMenu;
QWidget *m_pEditWidget;
QGridLayout *m_pEditLayout;
QLabel *m_pPeerIpAddressLabel;