feat: Add MPPSManager & MPPSAsyncAction
This commit is contained in:
179
src/dicom/MPPSAsyncAction.cpp
Normal file
179
src/dicom/MPPSAsyncAction.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include "MPPSAsyncAction.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <dcmtk/dcmnet/scu.h>
|
||||||
|
#include <dcmtk/dcmdata/dcpath.h>
|
||||||
|
#include <dcmtk/dcmdata/dctk.h>
|
||||||
|
#include <dcmtk/dcmdata/dcdict.h>
|
||||||
|
#include <dcmtk/dcmnet/diutil.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "json/jsonobject.h"
|
||||||
|
#include "MPPSSCU.h"
|
||||||
|
|
||||||
|
|
||||||
|
MPPSAsyncAction::MPPSAsyncAction(QObject* aParent):AsyncAction(aParent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MPPSAsyncAction::~MPPSAsyncAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPPSAsyncAction::run()
|
||||||
|
{
|
||||||
|
if (mPatient.isNull()||mPatient->PatientUID.isEmpty() || !mPatient->MPPSUID.isEmpty())return;
|
||||||
|
if (!dcmDataDict.isDictionaryLoaded())
|
||||||
|
{
|
||||||
|
qDebug() << "dcmdatadict error";
|
||||||
|
emit actionCompleted(ActionResult(Failed,tr("MPPS fail by dcmdatadict error!")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MPPSSCU scu;
|
||||||
|
host serverInfo = JsonObject::Instance()->getServer(JsonObject::MPPS);
|
||||||
|
|
||||||
|
/*scu*/
|
||||||
|
OFList<OFString> syntaxes;
|
||||||
|
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
|
||||||
|
scu.setMaxReceivePDULength(ASC_DEFAULTMAXPDU);
|
||||||
|
scu.setACSETimeout(30);
|
||||||
|
scu.setDIMSEBlockingMode(DIMSE_BLOCKING);
|
||||||
|
scu.setDIMSETimeout(0);
|
||||||
|
scu.setAETitle(serverInfo.localAE.toLatin1().data());
|
||||||
|
scu.setPeerHostName(serverInfo.ip.toLatin1().data());
|
||||||
|
scu.setPeerPort(OFstatic_cast(Uint16, serverInfo.port.toInt()));
|
||||||
|
scu.setPeerAETitle(serverInfo.ae.toLatin1().data());
|
||||||
|
scu.setVerbosePCMode(OFFalse);
|
||||||
|
scu.addPresentationContext(UID_ModalityPerformedProcedureStepSOPClass, syntaxes);
|
||||||
|
OFCondition cond = scu.initNetwork();
|
||||||
|
|
||||||
|
if (cond.bad())
|
||||||
|
{
|
||||||
|
qDebug() << cond.code() << cond.text();
|
||||||
|
qDebug() << "MPPS initNetwork failed";
|
||||||
|
emit actionCompleted(ActionResult(Failed,tr("MPPS initNetwork failed!")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cond = scu.negotiateAssociation();
|
||||||
|
if (cond.bad())
|
||||||
|
{
|
||||||
|
qDebug() << cond.code(); //<< "----"<<cond.text();
|
||||||
|
qDebug() << "MPPS connect failed";
|
||||||
|
emit actionCompleted(ActionResult(Failed,tr("MPPS connect failed!")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cond = EC_Normal;
|
||||||
|
T_ASC_PresentationContextID pcid = scu.findPresentationContextID(UID_ModalityPerformedProcedureStepSOPClass, "");
|
||||||
|
if (pcid == 0)
|
||||||
|
{
|
||||||
|
qDebug() << "MPPS pcid bad";
|
||||||
|
emit actionCompleted(ActionResult(Failed,tr("MPPS context error!")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DcmFileFormat dcmff;
|
||||||
|
DcmDataset *dset = dcmff.getDataset();
|
||||||
|
|
||||||
|
DcmSequenceOfItems *attr_Seq = new DcmSequenceOfItems(DCM_ScheduledStepAttributesSequence);
|
||||||
|
DcmItem *attr_item = new DcmItem();
|
||||||
|
|
||||||
|
attr_item->putAndInsertString(DCM_StudyInstanceUID, mPatient->StudyUID.toStdString().data());
|
||||||
|
|
||||||
|
DcmSequenceOfItems *refSeq = new DcmSequenceOfItems(DCM_ReferencedStudySequence);
|
||||||
|
attr_item->insert(refSeq);
|
||||||
|
attr_item->putAndInsertString(DCM_AccessionNumber, mPatient->AccessionNumber.toStdString().data());
|
||||||
|
|
||||||
|
attr_item->putAndInsertString(DCM_RequestedProcedureID, mPatient->RPID.toStdString().data());
|
||||||
|
attr_item->putAndInsertString(DCM_ScheduledProcedureStepID, mPatient->SPSID.toStdString().data());
|
||||||
|
DcmSequenceOfItems *protocolSeq = new DcmSequenceOfItems(DCM_ScheduledProtocolCodeSequence);
|
||||||
|
attr_item->insert(protocolSeq);
|
||||||
|
attr_Seq->insert(attr_item);
|
||||||
|
dset->insert(attr_Seq);
|
||||||
|
DcmSequenceOfItems *codeSeq = new DcmSequenceOfItems(DCM_ProcedureCodeSequence);
|
||||||
|
dset->insert(codeSeq);
|
||||||
|
dset->putAndInsertString(DCM_PatientName, mPatient->Name.toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PatientID, mPatient->ID.toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PatientBirthDate, mPatient->BirthDate.toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PatientSex, mPatient->Sex.toStdString().data());
|
||||||
|
DcmSequenceOfItems *refPSeq = new DcmSequenceOfItems(DCM_ReferencedPatientSequence);
|
||||||
|
dset->insert(refPSeq);
|
||||||
|
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepID, QDateTime::currentDateTime().toString("yyyyMMddHHmmss").toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PerformedStationAETitle, serverInfo.localAE.toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PerformedStationName, "");
|
||||||
|
dset->putAndInsertString(DCM_PerformedLocation, "");
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepStartDate,
|
||||||
|
QDateTime::currentDateTime().toString("yyyyMMdd").toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepStartTime,
|
||||||
|
QDateTime::currentDateTime().toString("hhmmss").toStdString().data());
|
||||||
|
// set status
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepStatus, "IN PROGRESS");
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepDescription, "");
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureTypeDescription, "");
|
||||||
|
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepEndDate, "");
|
||||||
|
dset->putAndInsertString(DCM_PerformedProcedureStepEndTime, "");
|
||||||
|
// get modality from MWL query resault
|
||||||
|
dset->putAndInsertString(DCM_Modality, mPatient->Modality.toStdString().data());
|
||||||
|
dset->putAndInsertString(DCM_StudyID, "");
|
||||||
|
|
||||||
|
DcmSequenceOfItems *refpPSeq = new DcmSequenceOfItems(DCM_PerformedProtocolCodeSequence);
|
||||||
|
dset->insert(refpPSeq);
|
||||||
|
// dset->print(std::cout);
|
||||||
|
Uint16 responses = 0;
|
||||||
|
|
||||||
|
OFString uid;
|
||||||
|
{
|
||||||
|
char uidbuff[100];
|
||||||
|
dcmGenerateUniqueIdentifier(uidbuff);
|
||||||
|
uid.append(uidbuff);
|
||||||
|
mPatient->MPPSUID = uidbuff;
|
||||||
|
}
|
||||||
|
cond = scu.sendNCreateRequest(pcid, uid, dset, responses);
|
||||||
|
bool result = true;
|
||||||
|
if (responses != 0)
|
||||||
|
{
|
||||||
|
OFString statusString;
|
||||||
|
const char *statusStringPtr = DU_ncreateStatusString(responses);
|
||||||
|
statusString.append(tr("MPPS fail by error:").toStdString().data());
|
||||||
|
statusString.append(statusStringPtr);
|
||||||
|
if (statusStringPtr != NULL)
|
||||||
|
{
|
||||||
|
// 输出错误消息
|
||||||
|
qDebug() << "Error Message: " << statusString.data() ;
|
||||||
|
}
|
||||||
|
emit actionCompleted(ActionResult(Failed,statusString.data()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cond == EC_Normal)
|
||||||
|
{
|
||||||
|
scu.releaseAssociation();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cond == DUL_PEERREQUESTEDRELEASE)
|
||||||
|
scu.closeAssociation(DCMSCU_PEER_REQUESTED_RELEASE);
|
||||||
|
else if (cond == DUL_PEERABORTEDASSOCIATION)
|
||||||
|
scu.closeAssociation(DCMSCU_PEER_ABORTED_ASSOCIATION);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scu.abortAssociation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit actionCompleted(ActionResult(Sucessed,QString("%0|%1").arg(mPatient->PatientUID).arg(mPatient->MPPSUID)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPPSAsyncAction::setPatient(PatientInformationPointer aPatient)
|
||||||
|
{
|
||||||
|
mPatient = aPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
PatientInformationPointer MPPSAsyncAction::getPatient()
|
||||||
|
{
|
||||||
|
return mPatient;
|
||||||
|
}
|
||||||
24
src/dicom/MPPSAsyncAction.h
Normal file
24
src/dicom/MPPSAsyncAction.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef GUI_MPPS_ASYNC_ACTION_H
|
||||||
|
#define GUI_MPPS_ASYNC_ACTION_H
|
||||||
|
|
||||||
|
#include "action/AsyncAction.h"
|
||||||
|
#include <forms/select/PatientInformation.h>
|
||||||
|
class MPPSAsyncAction : public AsyncAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MPPSAsyncAction(QObject* aParent);
|
||||||
|
~MPPSAsyncAction();
|
||||||
|
void run() override;
|
||||||
|
void setPatient(PatientInformationPointer aPatient);
|
||||||
|
PatientInformationPointer getPatient();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void actionCompleted(const ActionResult& aResult);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PatientInformationPointer mPatient;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GUI_MPPS_ASYNC_ACTION_H */
|
||||||
94
src/dicom/MPPSManager.cpp
Normal file
94
src/dicom/MPPSManager.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "MPPSManager.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDate>
|
||||||
|
|
||||||
|
#include "dialogs/MultyMessageDialogManager.h"
|
||||||
|
#include "db/SQLHelper.h"
|
||||||
|
#include "event/EventCenter.h"
|
||||||
|
#include "json/jsonobject.h"
|
||||||
|
#include "device/DeviceManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
void MPPSManager::setPatientUID(const QString& aPatientUID)
|
||||||
|
{
|
||||||
|
if (aPatientUID.isEmpty())return;
|
||||||
|
QMap<QString,QVariant> result;
|
||||||
|
QMap<QString,QVariant> parms;
|
||||||
|
parms[":patid"] = aPatientUID;
|
||||||
|
SQLHelper::QueryFirst("select * from Patient where PatientUID=:patid",result,parms);
|
||||||
|
PatientInformationPointer pat = PatientInformationPointer(new PatientInformation);
|
||||||
|
pat->PatientUID= result["PatientUID"].toString();
|
||||||
|
pat->ID = result["PatientID"].toString();
|
||||||
|
pat->AccessionNumber = result.contains("AccessionNumber")?result["AccessionNumber"].toString():"";
|
||||||
|
pat->Name = result["PatientName"].toString();
|
||||||
|
pat->Sex = result["Sex"].toString();
|
||||||
|
pat->BirthDate = result["BirthDate"].toString();
|
||||||
|
pat->StudyUID = result.contains("StudyUID")?result["StudyUID"].toString():"";
|
||||||
|
pat->RPID = result.contains("RPID")?result["RPID"].toString():"";
|
||||||
|
pat->SPSID = result.contains("SPSID")?result["SPSID"].toString():"";
|
||||||
|
pat->Modality = result.contains("Modality")?result["Modality"].toString():"CT";
|
||||||
|
pat->MPPSUID = result["MPPSUID"].toString();
|
||||||
|
action->setPatient(pat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPPSManager::processMPPSResult(const ActionResult& aResult)
|
||||||
|
{
|
||||||
|
if(aResult.Code == Failed){
|
||||||
|
MultyMessageDialogManager::getInstance()->raiseDialog(aResult.Data.toString(),MessageLevel::Warning);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
QStringList list = aResult.Data.toString().split("|");
|
||||||
|
if (list.length()<2)
|
||||||
|
{
|
||||||
|
MultyMessageDialogManager::getInstance()->raiseDialog(tr("Create MPPSUID error!"),MessageLevel::Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString sql = "update Patient set MPPSUID=:mppsuid where PatientUID=:patuid";
|
||||||
|
QMap<QString,QVariant> params;
|
||||||
|
params[":mppsuid"] = list[1];
|
||||||
|
params[":patuid"] = list[0];
|
||||||
|
|
||||||
|
int result = SQLHelper::ExecuteNoQuery(sql,params);
|
||||||
|
if(result<1)return;
|
||||||
|
MultyMessageDialogManager::getInstance()->raiseDialog(tr("Update MPPSUID success!"),MessageLevel::Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MPPSManager::MPPSManager():QObject(nullptr),action(new MPPSAsyncAction(nullptr))
|
||||||
|
{
|
||||||
|
connect(action,&MPPSAsyncAction::actionCompleted,this,&MPPSManager::processMPPSResult);
|
||||||
|
// connect(EventCenter::Default(),&EventCenter::SetSelectedPatient,[=](QObject* sender, QObject* data){
|
||||||
|
// PatientInformation* patientInfo = (PatientInformation*)data;
|
||||||
|
// if (JsonObject::Instance()->getMppsOpen()&&!patientInfo->SPSID.isEmpty()&&patientInfo->MPPSUID.isEmpty())
|
||||||
|
// {
|
||||||
|
// MPPSManager::getInstance()->setPatientUID(patientInfo->PatientUID);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
connect(DeviceManager::Default(), & DeviceManager::startAutoLocateResult,[=](bool result){
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
sendMPPS();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MPPSManager::~MPPSManager()
|
||||||
|
{
|
||||||
|
delete action;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPPSManager* MPPSManager::getInstance()
|
||||||
|
{
|
||||||
|
static MPPSManager instance;
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPPSManager::sendMPPS()
|
||||||
|
{
|
||||||
|
if (!action->getPatient()->MPPSUID.isEmpty())return;
|
||||||
|
action->execute();
|
||||||
|
}
|
||||||
28
src/dicom/MPPSManager.h
Normal file
28
src/dicom/MPPSManager.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef GUI_MPPSMANAGER_H
|
||||||
|
#define GUI_MPPSMANAGER_H
|
||||||
|
#include <QString>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include "MPPSAsyncAction.h"
|
||||||
|
#include "forms/select/PatientInformation.h"
|
||||||
|
|
||||||
|
class QSqlTableModel;
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
|
class MPPSManager:public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static MPPSManager *getInstance();
|
||||||
|
void sendMPPS();
|
||||||
|
void setPatientUID(const QString& aPatientID);
|
||||||
|
public slots:
|
||||||
|
void processMPPSResult(const ActionResult& aResult);
|
||||||
|
private:
|
||||||
|
MPPSManager();
|
||||||
|
~MPPSManager();
|
||||||
|
private:
|
||||||
|
MPPSAsyncAction* action;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GUI_MPPSMANAGER_H */
|
||||||
Reference in New Issue
Block a user