diff --git a/src/src/PACS/Network/MoveStoreScp.cpp b/src/src/PACS/Network/MoveStoreScp.cpp index e586eae..4569884 100644 --- a/src/src/PACS/Network/MoveStoreScp.cpp +++ b/src/src/PACS/Network/MoveStoreScp.cpp @@ -1,7 +1,14 @@ #include "MoveStoreScp.h" +namespace +{ + const int USCT_IMAGE_COUNT = 270 + 73 + 73; +} + MoveStoreScp::MoveStoreScp() - : DcmStorageSCP() + : QObject() + , DcmStorageSCP() + , mCount(0) { } @@ -10,3 +17,16 @@ bool MoveStoreScp::stopAfterCurrentAssociation() { return true; } + +OFCondition MoveStoreScp::handleIncomingCommand(T_DIMSE_Message *incomingMsg, const DcmPresentationContextInfo &presInfo) +{ + mCount++; + double progress = (double)mCount / (double)USCT_IMAGE_COUNT; + emit movePorgress(progress); + return DcmStorageSCP::handleIncomingCommand(incomingMsg, presInfo); +} + +void MoveStoreScp::clearCount() +{ + mCount = 0; +} diff --git a/src/src/PACS/Network/MoveStoreScp.h b/src/src/PACS/Network/MoveStoreScp.h index b6fbb5f..a45c712 100644 --- a/src/src/PACS/Network/MoveStoreScp.h +++ b/src/src/PACS/Network/MoveStoreScp.h @@ -1,13 +1,23 @@ #ifndef MOVESTORESCP_H #define MOVESTORESCP_H +#include #include "dcmtk/dcmnet/dstorscp.h" -class MoveStoreScp : public DcmStorageSCP +class MoveStoreScp : public QObject , public DcmStorageSCP { + Q_OBJECT public: MoveStoreScp(); bool stopAfterCurrentAssociation(); + virtual OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg, const DcmPresentationContextInfo &presInfo); + void clearCount(); + +signals: + void movePorgress(double aPorgress); + +private: + int mCount; }; #endif // MOVESTORESCP_H diff --git a/src/src/PACS/Network/MoveStoreThread.cpp b/src/src/PACS/Network/MoveStoreThread.cpp index 418d56f..b855fce 100644 --- a/src/src/PACS/Network/MoveStoreThread.cpp +++ b/src/src/PACS/Network/MoveStoreThread.cpp @@ -5,28 +5,29 @@ MoveStoreThread::MoveStoreThread(const std::string aAETitle, unsigned short aPor : QThread(aParent) , mAETitle(aAETitle) , mPort(aPort) + , mScp(new MoveStoreScp()) { - + mScp->setVerbosePCMode(false); + OFList syntaxes; + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + mScp->addPresentationContext(UID_CTImageStorage,syntaxes); + mScp->addPresentationContext(UID_MRImageStorage,syntaxes); + connect(mScp, &MoveStoreScp::movePorgress, this, &MoveStoreThread::moveProgress,Qt::DirectConnection); } MoveStoreThread::~MoveStoreThread() { + delete mScp; } void MoveStoreThread::run() { - MoveStoreScp scp; - scp.setAETitle(mAETitle); - scp.setPort(mPort); - scp.setVerbosePCMode(false); - scp.setOutputDirectory(mOutputPath); - OFList 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); + mScp->clearCount(); + mScp->setAETitle(mAETitle); + mScp->setPort(mPort); + mScp->setOutputDirectory(mOutputPath); + mScp->listen(); } void MoveStoreThread::setScpConfig(const std::string aAETitle, unsigned short aPort) diff --git a/src/src/PACS/Network/MoveStoreThread.h b/src/src/PACS/Network/MoveStoreThread.h index 4f3bded..7822b79 100644 --- a/src/src/PACS/Network/MoveStoreThread.h +++ b/src/src/PACS/Network/MoveStoreThread.h @@ -7,6 +7,7 @@ class MoveStoreScp; class MoveStoreThread : public QThread { + Q_OBJECT public: MoveStoreThread(const std::string aAETitle, unsigned short aPort, QObject* aParent = nullptr); ~MoveStoreThread(); @@ -14,10 +15,14 @@ public: void setScpConfig(const std::string aAETitle, unsigned short aPort); void setOutputPath(const std::string& aOutputPath); +signals: + void moveProgress(double aPorgress); + private: std::string mAETitle; unsigned short mPort; std::string mOutputPath; + MoveStoreScp* mScp; }; #endif // MOVESTORETHREAD_H diff --git a/src/src/PACS/Network/moveworker.cpp b/src/src/PACS/Network/moveworker.cpp index 8720ebd..4bd18de 100644 --- a/src/src/PACS/Network/moveworker.cpp +++ b/src/src/PACS/Network/moveworker.cpp @@ -2,34 +2,49 @@ #include "MoveStoreThread.h" #include "dcmtk/dcmnet/scu.h" -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) +MoveWorker::MoveWorker(unsigned long ourPort, const std::string& ourTitle, QObject *parent) : QObject(parent) , mMoveStoreThread(new MoveStoreThread(ourTitle, static_cast(ourPort),this)) , mScu(nullptr) - , mIsSendMoveMsgSucessed(false) { - mStrPeerIP = peerIP; - mUlPeerPort = peerPort; - mStrPeerTitle = peerTitle; mUlOurPort = ourPort; mStrOurTitle = ourTitle; - mStrOutputDirectory = outputDirectory; - connect(mMoveStoreThread,&QThread::finished,this,&MoveWorker::onMoveDone); + connect(mMoveStoreThread,&MoveStoreThread::moveProgress,this,&MoveWorker::notifyMoveProgress,Qt::DirectConnection); + setMoveStoreConfig(mStrOurTitle, mUlOurPort); +} + +MoveWorker::~MoveWorker() +{ + mMoveStoreThread->quit(); + mMoveStoreThread->wait(); + mMoveStoreThread->deleteLater(); + return; +} + +void MoveWorker::setMoveStoreConfig(const std::string aAETitle, unsigned short aPort) +{ + mMoveStoreThread->setScpConfig(aAETitle, aPort); } void MoveWorker::setOutputDirectory(const QString& outputDirectory) { mStrOutputDirectory = outputDirectory; mMoveStoreThread->setOutputPath(mStrOutputDirectory.toStdString()); + mMoveStoreThread->start(); } -void MoveWorker::setPacsInfo(const std::string& peerIP, unsigned long peerPort, const std::string& peerTitle, const std::string& ourTitle, unsigned long ourPort) +void MoveWorker::setListenInfo(const std::string& aOurTitle, unsigned long aOurPort) +{ + mUlOurPort = aOurPort; + mStrOurTitle = aOurTitle; + mMoveStoreThread->setScpConfig(mStrOurTitle, static_cast(mUlOurPort)); +} + +void MoveWorker::setPacsInfo(const std::string& peerIP, unsigned long peerPort, const std::string& peerTitle) { mStrPeerIP = peerIP; mUlPeerPort = peerPort; mStrPeerTitle = peerTitle; - mUlOurPort = ourPort; - mStrOurTitle = ourTitle; } bool MoveWorker::initDcmSCU() @@ -57,7 +72,7 @@ bool MoveWorker::initDcmSCU() return true; } -void MoveWorker::moveBySeriesUID(const QString& studyInstanceUID, const QString& seriesInstanceUID) +void MoveWorker::moveByStudyInstanceUID(const QString& studyInstanceUID) { if (!initDcmSCU()) { @@ -67,54 +82,45 @@ void MoveWorker::moveBySeriesUID(const QString& studyInstanceUID, const QString& mScu = nullptr; return; } - mMoveStoreThread->setScpConfig(mStrOurTitle,static_cast(mUlOurPort)); - mMoveStoreThread->start(); + T_ASC_PresentationContextID pcid = mScu->findPresentationContextID(UID_MOVEStudyRootQueryRetrieveInformationModel,""); OFList 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); - if(responses.begin() != responses.end() && (*responses.begin())->m_numberOfCompletedSubops > 0) - { - mIsSendMoveMsgSucessed = true; - } - else - { - mMoveStoreThread->terminate(); - } - if (cond.bad()|| cond != EC_Normal) { mScu->closeAssociation(DCMSCU_ABORT_ASSOCIATION); + emit notifyMoveDone(1, ""); } else { + if(responses.begin() != responses.end()) + { + auto lastResponse = responses.end(); + lastResponse = std::prev(lastResponse); + if((*lastResponse)->m_numberOfCompletedSubops>0) + { + emit notifyMoveDone(0, mStrOutputDirectory); + } + } mScu->releaseAssociation(); } + auto iter = responses.begin(); + auto last = responses.end(); + while (iter != last) + { + delete (*iter); + iter = responses.erase(iter); + } delete mScu; mScu = nullptr; } -void MoveWorker::onMoveDone() -{ - if(mIsSendMoveMsgSucessed) - { - emit notifyMoveDone(0, mStrOutputDirectory); - mIsSendMoveMsgSucessed = false; - } -} - -void MoveWorker::onMoveProgress(int progress, int total) -{ - emit notifyMoveProgress(progress, total); -} - void MoveWorker::onMoveStoreProgress(int code, QString filename) { emit notifyMoveStoreProgress(code, filename); diff --git a/src/src/PACS/Network/moveworker.h b/src/src/PACS/Network/moveworker.h index 1ddea71..8ec204f 100644 --- a/src/src/PACS/Network/moveworker.h +++ b/src/src/PACS/Network/moveworker.h @@ -11,34 +11,34 @@ class MoveWorker : public QObject Q_OBJECT public: - 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); + explicit MoveWorker( unsigned long ourPort, const std::string& ourTitle, QObject *parent = Q_NULLPTR); + ~MoveWorker(); + void setOutputDirectory(const QString& outputDir); + void setPacsInfo(const std::string& peerIP, unsigned long peerPort, const std::string& peerTitle); + void setListenInfo(const std::string& aOurTitle, unsigned long aOurPort); + Q_INVOKABLE void moveByStudyInstanceUID(const QString& studyInstanceUID); signals: - void notifyMoveDone(int, QString dir); - void notifyMoveProgress(int, int); - void notifyMoveStoreProgress(int, QString); + void notifyMoveDone(int, QString dir); + void notifyMoveProgress(double aProgress); + void notifyMoveStoreProgress(int, QString); public slots: - void onMoveProgress(int, int); - void onMoveStoreProgress(int, QString); - void onMoveDone(); + void onMoveStoreProgress(int, QString); private: bool initDcmSCU(); + void setMoveStoreConfig(const std::string aAETitle, unsigned short aPort); private: std::string mStrPeerIP; - unsigned long long mUlPeerPort; + unsigned long mUlPeerPort; std::string mStrPeerTitle; - unsigned long long mUlOurPort; + unsigned long mUlOurPort; std::string mStrOurTitle; QString mStrOutputDirectory; MoveStoreThread* mMoveStoreThread; DcmSCU* mScu; - bool mIsSendMoveMsgSucessed; }; diff --git a/src/src/PACS/Network/queryworker.cpp b/src/src/PACS/Network/queryworker.cpp index 4418de9..3df943d 100644 --- a/src/src/PACS/Network/queryworker.cpp +++ b/src/src/PACS/Network/queryworker.cpp @@ -189,6 +189,30 @@ void QueryWorker::queryBySeriesUID(const QString& studyInstanceUID) m_QueryDataSet->putAndInsertOFStringArray(DCM_QueryRetrieveLevel,"STUDY"); } +void QueryWorker::queryByDeviceName(const QString& aDeviceName) +{ + m_iQueryLevel = 0; + m_QueryDataSet->putAndInsertOFStringArray(DCM_StationName,aDeviceName.toStdString()); + executeCFind(m_QueryDataSet); + m_QueryDataSet->putAndInsertOFStringArray(DCM_StationName,""); +} + +void QueryWorker::queryByDeviceNameAndDate(const QString& aDeviceName, const QString& studyStartDate, const QString& studyEndDate) +{ + m_iQueryLevel = 0; + initQueryDataSet(); + m_QueryDataSet->putAndInsertOFStringArray(DCM_StationName,aDeviceName.toStdString()); + QString dateQuery = studyStartDate; + if(!studyEndDate.isEmpty()) + { + dateQuery += "-"+studyEndDate; + } + m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,dateQuery.toStdString()); + executeCFind(m_QueryDataSet); + m_QueryDataSet->putAndInsertOFStringArray(DCM_StationName,""); + m_QueryDataSet->putAndInsertOFStringArray(DCM_StudyDate,""); +} + void QueryWorker::onFoundResult(int index, DcmDataset *response) { std::string studyDate_, patientName_, patientID_, accessionNumber_, diff --git a/src/src/PACS/Network/queryworker.h b/src/src/PACS/Network/queryworker.h index b886382..0b0b5a5 100644 --- a/src/src/PACS/Network/queryworker.h +++ b/src/src/PACS/Network/queryworker.h @@ -24,6 +24,8 @@ public: Q_INVOKABLE void queryByAccessNo(const QString& accsessionNo); Q_INVOKABLE void queryByAccessNoAndDate(const QString& accessionNo, const QString& studyStartDate, const QString& studyEndDate); Q_INVOKABLE void queryBySeriesUID(const QString& studyInstanceUID); + Q_INVOKABLE void queryByDeviceName(const QString& aDeviceName); + Q_INVOKABLE void queryByDeviceNameAndDate(const QString& aDeviceName, const QString& studyStartDate, const QString& studyEndDate); signals: void sendFindDone(int); diff --git a/src/src/PACS/Widget/importwidget.cpp b/src/src/PACS/Widget/importwidget.cpp index d092fbd..0f895d1 100644 --- a/src/src/PACS/Widget/importwidget.cpp +++ b/src/src/PACS/Widget/importwidget.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "PACS/Dialog/promptdialog.h" #include "PACS/Common/dicomviewerhelper.h" @@ -41,7 +42,6 @@ ImportWidget::ImportWidget(QWidget *parent) , m_pClearButton(nullptr) , m_pDateComboBox(nullptr) , m_pStudyResult(nullptr) - , m_pSeriesResult(nullptr) , m_pSettingDialog(nullptr) , m_pMsgBox(nullptr) , m_CallbackHelper(nullptr) @@ -60,6 +60,7 @@ ImportWidget::ImportWidget(QWidget *parent) qRegisterMetaType("PACSSeriesInfo"); initUi(); initSys(); + initMoveWorker(); } ImportWidget::~ImportWidget() @@ -85,18 +86,11 @@ ImportWidget::~ImportWidget() delete mMoveWorkerThread; mMoveWorkerThread = nullptr; } - - if (mMoveWorker != nullptr) - { - delete mMoveWorker; - mMoveWorker = nullptr; - } - } void ImportWidget::initUi() { - //this->setWindowFlags(Qt::FramelessWindowHint); + //this->setWindowFlags(Qt::FramelessWindowHint); this->setWindowTitle(tr("PACS Configuration")); this->resize(780, 470); this->setMinimumSize(QSize(780, 470)); @@ -143,26 +137,21 @@ void ImportWidget::initUi() m_pStudyResult = new QTableView(this); m_pMainLayout->addWidget(m_pStudyResult); - m_pSeriesResult = new QTableView(this); - m_pMainLayout->addWidget(m_pSeriesResult); - m_pProgressWidget = new QWidget(this); - m_pProgressLayout = new QHBoxLayout(m_pProgressWidget); - m_pProgressLayout->setAlignment(Qt::AlignRight); - m_pProgressItem = new QSpacerItem(200, 10, QSizePolicy::Expanding, QSizePolicy::Expanding); - m_pProgressLayout->addItem(m_pProgressItem); + m_pProgressWidget = new QWidget(this); + m_pProgressLayout = new QHBoxLayout(m_pProgressWidget); + m_pProgressLayout->setContentsMargins(0,0,0,0); m_pProgressBar = new QProgressBar(m_pProgressWidget); + m_pProgressBar->setAlignment(Qt::AlignCenter); m_pProgressLayout->addWidget(m_pProgressBar); m_pMainLayout->addWidget(m_pProgressWidget); - //m_pProgressWidget->setVisible(false); initFilterPacs(); initFilterModality(); initFilterDate(); initFilterDicom(); - initStudy(); - initSeries(); + initStudy();; } void ImportWidget::initSys() @@ -174,9 +163,9 @@ void ImportWidget::initSys() connect(m_pSettingButton, SIGNAL(clicked()), this, SLOT(configure())); connect(m_pSearchButton, SIGNAL(clicked()), this, SLOT(query())); connect(m_pClearButton, SIGNAL(clicked()), this, SLOT(clear())); - connect(m_pStudyResult, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onStudySelected(const QModelIndex &))); - connect(m_pSeriesResult, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onSeriesSelected(const QModelIndex &))); - connect(m_pSeriesResult, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(onSeriesDoubleClicked(const QModelIndex &))); + connect(m_pStudyResult, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(onSeriesDoubleClicked(const QModelIndex &))); +// connect(m_pSeriesResult, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onSeriesSelected(const QModelIndex &))); +// connect(m_pSeriesResult, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(onSeriesDoubleClicked(const QModelIndex &))); connect(m_pDateComboBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(onDateFilterChanged(const QString &))); } @@ -231,6 +220,7 @@ void ImportWidget::initFilterDicom() m_pDicomComboBox->addItem(tr("Patient name")); m_pDicomComboBox->addItem(tr("Patient ID")); m_pDicomComboBox->addItem(tr("Accession number")); + m_pDicomComboBox->addItem(tr("Device name")); //m_pDicomComboBox->addItem("Study description"); //m_pDicomComboBox->addItem("Referring physician"); //m_pDicomComboBox->addItem("Performing physician"); @@ -242,9 +232,9 @@ void ImportWidget::initStudyHeader() { m_lStudyHeaders.clear(); m_lStudyHeaders << tr("Study date") << tr("Patient name") << tr("Date of birth") << tr("Patient ID") - << tr("Modality") << tr("Study description") << tr("Accession number") << tr("Exam ID") + << tr("Modality") << tr("Study ID") << tr("Study Instance Uid") << tr("Accession number") << tr("Referring physician") << tr("Performing physician") << tr("Reading physician") << tr("Institution name") - << tr("Images") << tr("Source") << tr("uid"); + << tr("Images") << tr("Source"); } void ImportWidget::initStudy() @@ -262,52 +252,44 @@ void ImportWidget::initStudy() m_pStudyResult->setModel(m_pStudyModel); } -void ImportWidget::initSeriesHeader() +void ImportWidget::initMoveWorker() { - m_lSeriesHeaders.clear(); - m_lSeriesHeaders << tr("#") << tr("Number") << tr("Modality") << tr("Description") << tr("#Images"); -} - -void ImportWidget::initSeries() -{ - initSeriesHeader(); - m_pSeriesModel = new QStandardItemModel; - m_pSeriesModel->setHorizontalHeaderLabels(m_lSeriesHeaders); - //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); - m_pSeriesResult->setSelectionBehavior(QAbstractItemView::SelectRows); - m_pSeriesResult->setModel(m_pSeriesModel); + unsigned long ourPort = DicomViewerHelper::ourPort().toULong(); + std::string ourTitle = DicomViewerHelper::ourTitle().toStdString(); + mMoveWorkerThread = new QThread(); + mMoveWorker = new MoveWorker(ourPort, ourTitle); + mMoveWorker->moveToThread(mMoveWorkerThread); + connect(mMoveWorker, SIGNAL(notifyMoveDone(int, QString)), this, SLOT(moveDone(int, QString)), Qt::QueuedConnection); + connect(mMoveWorker, SIGNAL(notifyMoveProgress(double)), this, SLOT(moveProgress(double)), Qt::QueuedConnection); + connect(mMoveWorker, SIGNAL(notifyMoveStoreProgress(int, QString)), this, SLOT(moveStoreProgress(int, QString)), Qt::QueuedConnection); + connect(mMoveWorkerThread, &QThread::finished, mMoveWorker, &QObject::deleteLater); + mMoveWorkerThread->start(); } bool ImportWidget::eventFilter(QObject *obj, QEvent *event) { - if (m_pTitleBar == obj) - { - if (event->type() == QEvent::MouseButtonPress) - { - QRect dragArea = m_pTitleBar->geometry(); - if (dragArea.contains(mapFromGlobal(QCursor::pos())) && !this->isMaximized()) - { - m_dragState.dragging = true; - m_dragState.dragStartPosition = QCursor::pos(); - } - } - else if (event->type() == QEvent::MouseButtonRelease) - { - m_dragState.dragging = false; - } - else if (m_dragState.dragging && event->type() == QEvent::MouseMove) - { - const QPoint& curPos = QCursor::pos(); - this->move(this->geometry().topLeft() + (curPos - m_dragState.dragStartPosition)); - m_dragState.dragStartPosition = curPos; - } - } +// if (m_pTitleBar == obj) +// { +// if (event->type() == QEvent::MouseButtonPress) +// { +// QRect dragArea = m_pTitleBar->geometry(); +// if (dragArea.contains(mapFromGlobal(QCursor::pos())) && !this->isMaximized()) +// { +// m_dragState.dragging = true; +// m_dragState.dragStartPosition = QCursor::pos(); +// } +// } +// else if (event->type() == QEvent::MouseButtonRelease) +// { +// m_dragState.dragging = false; +// } +// else if (m_dragState.dragging && event->type() == QEvent::MouseMove) +// { +// const QPoint& curPos = QCursor::pos(); +// this->move(this->geometry().topLeft() + (curPos - m_dragState.dragStartPosition)); +// m_dragState.dragStartPosition = curPos; +// } +// } return QDialog::eventFilter(obj, event); } @@ -366,7 +348,6 @@ unsigned short ImportWidget::getProtocol() void ImportWidget::onQueryDone(int code) { updateStudyView(); - updateSeriesView(); } void ImportWidget::getDateIntervalForQuery(QString& startDate, QString& endDate) @@ -491,6 +472,13 @@ void ImportWidget::query() else QMetaObject::invokeMethod(mQueryWorker, "queryByAccessNoAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate)); } + else if (m_pDicomComboBox->currentText() == tr("Device name")) + { + if (m_pDateComboBox->currentText() == tr("All dates") || m_pDateComboBox->currentText() == "-----------") + QMetaObject::invokeMethod(mQueryWorker, "queryByDeviceName", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text())); + else + QMetaObject::invokeMethod(mQueryWorker, "queryByDeviceNameAndDate", Qt::QueuedConnection, Q_ARG(QString, m_pDicomEdit->text()), Q_ARG(QString, studyStartDate), Q_ARG(QString, studyEndDate)); + } } void ImportWidget::onStudyFoundResult(PACSStudyInfo studyInfo) @@ -514,19 +502,19 @@ void ImportWidget::updateStudyView() QStandardItem* birth = new QStandardItem(itr->patientBirthDate); birth->setEditable(false); QStandardItem* id = new QStandardItem(itr->patientID); id->setEditable(false); QStandardItem* modality = new QStandardItem(""); modality->setEditable(false); - QStandardItem* description = new QStandardItem(""); description->setEditable(false); + QStandardItem* studyID = new QStandardItem(itr->studyID); studyID->setEditable(false); QStandardItem* accNo = new QStandardItem(itr->accessionNumber); accNo->setEditable(false); - QStandardItem* examId = new QStandardItem(""); examId->setEditable(false); + QStandardItem* uid = new QStandardItem(itr->studyInstanceUID); uid->setEditable(false); QStandardItem* referPhy = new QStandardItem(""); referPhy->setEditable(false); QStandardItem* performPhy = new QStandardItem(""); performPhy->setEditable(false); QStandardItem* readingPhysician = new QStandardItem(itr->requestingPhysician); readingPhysician->setEditable(false); QStandardItem* inst = new QStandardItem(""); inst->setEditable(false); QStandardItem* image = new QStandardItem(""); image->setEditable(false); QStandardItem* source = new QStandardItem(m_pPacsComboBox->currentText()); source->setEditable(false); - QStandardItem* uid = new QStandardItem(itr->studyInstanceUID); uid->setEditable(false); + QList list; - list << date << name << birth << id << modality << description << accNo << examId << referPhy - << performPhy << readingPhysician << inst << image << source << uid; + list << date << name << birth << id << modality << studyID << uid << accNo << referPhy + << performPhy << readingPhysician << inst << image << source; m_pStudyModel->insertRow(iRowIdx, list); ++iRowIdx; } @@ -562,67 +550,55 @@ void ImportWidget::updateStudyView() void ImportWidget::onStudySelected(const QModelIndex ¤t) { - int row = current.row(); - if (row < 0) - return; +// int row = current.row(); +// if (row < 0) +// return; - if (mQueryWorkerThread == nullptr) - { - mQueryWorkerThread = new QThread; - } - else - { - if (!mQueryWorkerThread->isFinished()) - { - mQueryWorkerThread->exit(); - mQueryWorkerThread->wait(); - } - } +// if (mQueryWorkerThread == nullptr) +// { +// mQueryWorkerThread = new QThread; +// } +// else +// { +// if (!mQueryWorkerThread->isFinished()) +// { +// mQueryWorkerThread->exit(); +// mQueryWorkerThread->wait(); +// } +// } - if (mQueryWorker == 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 (mQueryWorker == 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; +// } - 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); - } - mQueryWorker->moveToThread(mQueryWorkerThread); - mQueryWorkerThread->start(); +// 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); +// } +// mQueryWorker->moveToThread(mQueryWorkerThread); +// mQueryWorkerThread->start(); - m_seriesInfo.clear(); - std::string studyInstanceUID = m_pStudyModel->index(row, 14).data().toString().toStdString(); - QMetaObject::invokeMethod(mQueryWorker, "queryBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID))); +// m_seriesInfo.clear(); +// std::string studyInstanceUID = m_pStudyModel->index(row, 14).data().toString().toStdString(); +// QMetaObject::invokeMethod(mQueryWorker, "queryBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID))); } void ImportWidget::onSeriesFoundResult(PACSSeriesInfo seriesInfo) { m_seriesInfo.push_back(seriesInfo); - updateSeriesView(); } -void ImportWidget::onSeriesSelected(const QModelIndex ¤t) -{ - int row = current.row(); - if (row < 0) - return; - if (currentSeriesRow != row) - currentSeriesRow = row; - if (m_pProgressBar != nullptr) - m_pProgressBar->setValue(0); -} - - void ImportWidget::onSeriesDoubleClicked(const QModelIndex ¤t) { + m_pStudyResult->setEnabled(false); if(getProtocol() == 1) { executeCGet(current); @@ -639,56 +615,28 @@ void ImportWidget::executeCMove(const QModelIndex ¤t) if (row < 0) return; - if (currentSeriesRow != row && m_pProgressBar != nullptr) + if (m_pProgressBar != nullptr) { m_pProgressBar->setValue(0); - currentSeriesRow = row; } - 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 seriesNumber = m_pSeriesModel->index(row, 1).data().toString().toStdString(); + std::string studyInstanceUID = m_pStudyModel->index(row, 6).data().toString().toStdString(); + std::string studyID = m_pStudyModel->index(row, 5).data().toString().toStdString(); + //std::string seriesUID = m_pSeriesModel->index(row, 6).data().toString().toStdString(); + std::string patientName = m_pStudyModel->index(row, 1).data().toString().toStdString(); std::string outDirectory = DicomViewerHelper::applicationPath().toStdString(); outDirectory += "/"; outDirectory += studyInstanceUID; - outDirectory += "/"; - outDirectory += seriesUID; + //outDirectory += "/"; + //outDirectory += seriesUID; bool mkRet = false; QDir d(QString::fromStdString(outDirectory)); if (!d.exists()) mkRet = d.mkpath(QString::fromStdString(outDirectory)); - 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; - } - 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); @@ -696,13 +644,10 @@ void ImportWidget::executeCMove(const QModelIndex ¤t) { return; } - mMoveWorker->setPacsInfo(peerIP,peerPort,peerTitle,ourTitle,ourPort); + mMoveWorker->setPacsInfo(peerIP,peerPort,peerTitle); mMoveWorker->setOutputDirectory(QString::fromStdString(outDirectory)); - mMoveWorker->moveToThread(mQueryWorkerThread); - mMoveWorkerThread->start(); - 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))); + QMetaObject::invokeMethod(mMoveWorker, "moveByStudyInstanceUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID))); } void ImportWidget::executeCGet(const QModelIndex ¤t) @@ -711,10 +656,9 @@ void ImportWidget::executeCGet(const QModelIndex ¤t) if (row < 0) return; - if (currentSeriesRow != row && m_pProgressBar != nullptr) + if (m_pProgressBar != nullptr) { m_pProgressBar->setValue(0); - currentSeriesRow = row; } if (mGetWorkerThread == nullptr) @@ -765,19 +709,28 @@ void ImportWidget::executeCGet(const QModelIndex ¤t) 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))); + QMetaObject::invokeMethod(mGetWorker, "moveBySeriesUID", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(studyInstanceUID)), Q_ARG(QString, QString::fromStdString(seriesInstanceUID)), Q_ARG(QString, QString::fromStdString(dicomType))); } void ImportWidget::moveDone(int code, QString dir) { - emit sigMoveDone(code, dir.toStdString()); + m_pStudyResult->setEnabled(true); + m_pProgressBar->setValue(0); + if(code == 0) + { + emit sigMoveDone(code, dir.toStdString()); + reject(); + } + else + { + QMessageBox::warning(this, "error", "Download dicom failed"); + } } -void ImportWidget::moveProgress(int completed, int total) +void ImportWidget::moveProgress(double aProgress) { - double fP = (double)completed / total; - int iP = (int)(fP * 100); + int iP = (int)(aProgress * 100); if (m_pProgressBar != nullptr) m_pProgressBar->setValue(iP); } @@ -788,42 +741,6 @@ void ImportWidget::moveStoreProgress(int, QString) } -void ImportWidget::updateSeriesView() -{ - m_pSeriesModel->clear(); - m_pSeriesModel->setHorizontalHeaderLabels(m_lSeriesHeaders); - int iRowIdx = 0; - - QList::const_iterator itr = m_seriesInfo.begin(); - for(; itr != m_seriesInfo.end(); ++itr) - { - int idx = iRowIdx + 1; - QString i; - i.setNum(idx); - QStandardItem* index = new QStandardItem(i); index->setEditable(false); - QStandardItem* number = new QStandardItem(itr->seriesNumber); number->setEditable(false); - QStandardItem* modality = new QStandardItem(itr->modality); modality->setEditable(false); - QStandardItem* Image = new QStandardItem(""); Image->setEditable(false); - QStandardItem* studyUID = new QStandardItem(itr->studyInstanceUID); studyUID->setEditable(false); - QStandardItem* studyID = new QStandardItem(itr->studyID); studyID->setEditable(false); - QStandardItem* seriesUID = new QStandardItem(itr->seriesUID); seriesUID->setEditable(false); - QStandardItem* patientName = new QStandardItem(itr->patientName); patientName->setEditable(false); - QList list; - list << index << number << modality << Image << studyUID << studyID << seriesUID << patientName; - m_pSeriesModel->insertRow(iRowIdx, list); - ++iRowIdx; - } - m_pSeriesResult->setModel(m_pSeriesModel); - - m_pSeriesResult->setColumnHidden(4, true); // StudyInstanceUID; - m_pSeriesResult->setColumnHidden(5, true); // StudyID; - m_pSeriesResult->setColumnHidden(6, true); // SeriesInstanceUID; - m_pSeriesResult->setColumnHidden(7, true); // PatientName; - - if (m_pProgressBar != nullptr) - m_pProgressBar->setValue(0); -} - void ImportWidget::clear() { m_pStudyModel->clear(); diff --git a/src/src/PACS/Widget/importwidget.h b/src/src/PACS/Widget/importwidget.h index 4b9cd0e..08da273 100644 --- a/src/src/PACS/Widget/importwidget.h +++ b/src/src/PACS/Widget/importwidget.h @@ -59,10 +59,9 @@ public slots: void onSeriesFoundResult(PACSSeriesInfo); //////void onFoundResult(int index, DcmDataset *response); void onStudySelected(const QModelIndex &); - void onSeriesSelected(const QModelIndex &); void onSeriesDoubleClicked(const QModelIndex &); void moveDone(int, QString); - void moveProgress(int, int); + void moveProgress(double); void moveStoreProgress(int, QString); protected: @@ -77,8 +76,7 @@ private: void initFilterDicom(); void initStudyHeader(); void initStudy(); - void initSeriesHeader(); - void initSeries(); + void initMoveWorker(); void getNetParams(std::string& peerIP, unsigned long& peerPort, std::string& peerTitle, unsigned long& ourPort, std::string& ourTitle); void updateStudyView(); void updateSeriesView(); @@ -102,11 +100,10 @@ private: QPushButton *m_pSearchButton; QPushButton *m_pClearButton; QTableView *m_pStudyResult; - QTableView *m_pSeriesResult; QWidget *m_pFilterWidget; QWidget *m_pProgressWidget; - QHBoxLayout *m_pProgressLayout; + QHBoxLayout *m_pProgressLayout; QSpacerItem *m_pProgressItem; QProgressBar *m_pProgressBar; //RadiusProgressBar *m_pProgressBar; @@ -127,8 +124,6 @@ private: QList m_studyInfo; QList m_seriesInfo; - int currentSeriesRow; - QThread* mQueryWorkerThread; QueryWorker* mQueryWorker; QThread* mMoveWorkerThread; diff --git a/src/src/UI/Window/QDicomViewer.cpp b/src/src/UI/Window/QDicomViewer.cpp index b39ca28..6212e7e 100644 --- a/src/src/UI/Window/QDicomViewer.cpp +++ b/src/src/UI/Window/QDicomViewer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Common/Helper/OrientationHelper.h" diff --git a/src/translations/en_US.ts b/src/translations/en_US.ts index 57ab734..e4ea018 100644 --- a/src/translations/en_US.ts +++ b/src/translations/en_US.ts @@ -94,27 +94,27 @@ Customwindow - + Customwindow - + Window level - + Window width - + OK - + Cancel @@ -182,212 +182,219 @@ - + + + + CUR STATE: %1 + + + + Adjust window level - + Custom Window - + Negative - + Pan image - + Zoom image - + Browse series - + Toggle annotations - + Annotations - + Cross Reference Line - + Hide all measurements - + Hide patient data - + Show Dicom tags - + Length - + Angle - + Closed polygon - + Open polygon - + Arrow - + Ellipse - + Text - + Measurements - + Delete selected - + Delete all in current slice - + Delete all in current series - + Fusion - + Cine - + Delete current series - + Transformations - + Rotate 90 CCW - + Rotate 90 CW - + Rotate 180 - + Flip horizontal - + Flip vertical - + Clear transformations - + MPR - + 3D MPR - + Coronal - + Sagittal - + Axial - + Full screen - + Exit full screen mode - + Minimize - + Close @@ -395,12 +402,12 @@ DicomImageView - + Error - + Unable to read file %1 @@ -441,17 +448,17 @@ EllipseAnnotationActor - + mm² - + cm² - + Area @@ -459,122 +466,122 @@ ExportDialog - + Dialog - + Export Type - + Export File - + Current Image - + Current Series - + All Opened Series - + File Format - + JPEG - + BMP - + PNG - + TIFF - + DICOM - + Export Location - + Export Folder - + FileName Prefix - + Choose Folder... - + Show in Explorer after exported - + File Settings - + Annotations - + Full - + Basic(anonymous) - + Disabled - + Export - + Close @@ -611,77 +618,30 @@ FontPropertyWidget - + Text Property - + Specify the path to a TTF file here. - + Apply - - Resets any changed properties to their values from the last time 'Apply' was clicked. - - - - - Reset - - - - - Delete - - - - - Select font - - - - - Set font size - - - - - Set font opacity - - - - - Bold - - - - - - - ... - - - - - Italics - - - - - Shadow + + Cancel GridPopWidget - + Form @@ -697,173 +657,154 @@ ImportWidget - + Search - + Clear - + Study date - - - + + + Patient name - + Date of birth - - - + + + Patient ID - - + Modality - - Study description + + Study ID - - - - Accession number - - - - - PACS Configuration - - - - - All modalities - - - - - - - - All dates - - - - - - Today - - - - - - Yesterday - - - - - - This week + + Study Instance Uid - + + + Accession number + + + + + PACS Configuration + + + + + All modalities + + + + + + + + + All dates + + + + + + Today + + + + + + Yesterday + + + + + + This week + + + + + This month - - - + + + Custom date - - - + + + Custom date range - - Exam ID + + + Device name - + Referring physician - + Performing physician - + Reading physician - + Institution name - + Images - + Source - - - uid - - - - - # - - - - - Number - - - - - Description - - - - - #Images - - MyTitleBar @@ -881,32 +822,32 @@ OpenPolyAnnotationActor - + mm - + cm - + mm² - + cm² - + Distance - + Area @@ -930,47 +871,47 @@ QDicomViewer - + Ready - + Open dicom directory - + Open dicom files - + confirm - + Change Language will reload the application, please confirm to do this! - + Ok - + Cancel - + Warning - + open DICOM Images From PACS Fail @@ -978,12 +919,12 @@ QDicomViewerClass - + QDicomViewer - + toolBar @@ -1035,32 +976,32 @@ VCRToolbar - + VCR Controls - + &Play - + Pre&vious Frame - + &First Frame - + &Next Frame - + &Last Frame @@ -1126,27 +1067,27 @@ calibrationWidget - + Length Calibration - + Enter new distance - + mm - + OK - + Cancel diff --git a/src/translations/zh_CN.ts b/src/translations/zh_CN.ts index 43b957f..5fcdff0 100644 --- a/src/translations/zh_CN.ts +++ b/src/translations/zh_CN.ts @@ -94,27 +94,27 @@ Customwindow - + Customwindow 自定义窗宽窗位 - + Window level 窗位 - + Window width 窗宽 - + OK 确定 - + Cancel 取消 @@ -157,8 +157,11 @@ 激活图像同步 + + + CUR STATE: %1 - 当前状态: %1 + 当前状态: %1 @@ -186,212 +189,212 @@ 同步窗宽窗位 - + Adjust window level 调窗 - + Custom Window 自定义窗宽窗位 - + Negative 负相 - + Pan image 移动 - + Zoom image 缩放 - + Browse series 翻页 - + Toggle annotations 四角标记 - + Annotations 四角标记 - + Cross Reference Line 参考线 - + Hide all measurements 隐藏所有测量 - + Hide patient data 隐藏患者信息 - + Show Dicom tags 显示DICOM标记 - + Length 直尺 - + Angle 量角器 - + Closed polygon 闭合多边形 - + Open polygon 开放多边形 - + Arrow 箭头 - + Ellipse 椭圆 - + Text 文字 - + Measurements 测量工具 - + Delete selected 删除选中 - + Delete all in current slice 删除当前图像中所有测量 - + Delete all in current series 删除当前序列所有图像 - + Fusion - + Cine - + Delete current series 删除当前序列所有测量 - + Transformations 翻页&旋转 - + Rotate 90 CCW 逆时针旋转90度 - + Rotate 90 CW 顺时针旋转90度 - + Rotate 180 旋转180度 - + Flip horizontal 水平翻转 - + Flip vertical 垂直翻转 - + Clear transformations 清除变换 - + MPR 多平面重建 - + 3D MPR - + Coronal 冠状面 - + Sagittal 矢状面 - + Axial 横断面 - + Full screen 全屏 - + Exit full screen mode 退出全屏 - + Minimize 最小化 - + Close 关闭 @@ -399,12 +402,12 @@ DicomImageView - + Error 错误 - + Unable to read file %1 无法读取文件 %1 @@ -445,17 +448,17 @@ EllipseAnnotationActor - + mm² 平方毫米 - + cm² 平方厘米 - + Area 面积 @@ -463,122 +466,122 @@ ExportDialog - + Dialog - + Export Type - + Export File - + Current Image - + Current Series - + All Opened Series - + File Format - + JPEG - + BMP - + PNG - + TIFF - + DICOM - + Export Location - + Export Folder - + FileName Prefix - + Choose Folder... - + Show in Explorer after exported - + File Settings - + Annotations 四角标记 - + Full - + Basic(anonymous) - + Disabled - + Export - + Close 关闭 @@ -615,77 +618,34 @@ FontPropertyWidget - + Text Property 文字属性 - + Specify the path to a TTF file here. - + Apply 应用 - - Resets any changed properties to their values from the last time 'Apply' was clicked. - + + Cancel + 取消 - - Reset - - - - Delete - 删除 - - - - Select font - - - - - Set font size - - - - - Set font opacity - - - - - Bold - - - - - - - ... - - - - - Italics - - - - - Shadow - + 删除 GridPopWidget - + Form @@ -701,172 +661,173 @@ ImportWidget - + Search 搜索 - + Clear 清除 - + Study date 检查日期 - - - + + + Patient name 患者姓名 - + Date of birth 出生日期 - - - + + + Patient ID 患者编码 - - + + + Device name + 设备名称 + + + Modality 模态 - - Study description - 检查描述 + + Study ID + - - - + + Study Instance Uid + + + + Study description + 检查描述 + + + + + Accession number 检查单号 - + PACS Configuration PACS设置 - + All modalities 所有模态 - - - - + + + + + All dates 所有日期 - - + + Today 今天 - - + + Yesterday 昨天 - - + + This week 本周 - - + + This month 本月 - - - + + + Custom date 自定义日期 - - - + + + Custom date range 自定义时间段 - Exam ID - 检查编码 + 检查编码 - + Referring physician 转诊医生 - + Performing physician 检查医生 - + Reading physician 阅片医生 - + Institution name 机构名称 - + Images 图像数量 - + Source 数据源 - - uid - - - - - # - - - - Number - 序列号 + 序列号 - Description - 描述 + 描述 - #Images - 数量 + 数量 @@ -885,27 +846,27 @@ OpenPolyAnnotationActor - + mm 毫米 - + cm 厘米 - + mm² 平方毫米 - + cm² 平方厘米 - + Distance 周长 @@ -914,7 +875,7 @@ 直径 - + Area 面积 @@ -938,47 +899,47 @@ QDicomViewer - + Ready 就绪 - + Open dicom directory 打开文件夹 - + Open dicom files 打开文件 - + confirm 确认 - + Change Language will reload the application, please confirm to do this! 更改语言会重载整个程序,请确认是否要如此操作! - + Ok 确认 - + Cancel 取消 - + Warning 警告 - + open DICOM Images From PACS Fail 从PACS打开 @@ -986,12 +947,12 @@ QDicomViewerClass - + QDicomViewer - + toolBar @@ -1050,32 +1011,32 @@ VCRToolbar - + VCR Controls - + &Play - + Pre&vious Frame - + &First Frame - + &Next Frame - + &Last Frame @@ -1145,27 +1106,27 @@ calibrationWidget - + Length Calibration - + Enter new distance - + mm 毫米 - + OK 确定 - + Cancel 取消