#include "ScanFormWidget.h" #include "ui_TabFormWidget.h" #include #include #include #include #include #include #include #include #include "forms/scan/PatientInformationForm.h" #include "event/EventCenter.h" #include "dialogs/DialogManager.h" #include "log/LogManager.h" #include "json/jsonobject.h" #include "device/DeviceManager.h" #include "dicom/WorkListManager.h" #include "components/CoordinateXYWidget.h" #include "components/CoordinateZWidget.h" #include "utilities/ScanProcessSequence.h" #include "dicom/MPPSManager.h" #ifdef WIN32 #else #include #endif namespace { const size_t PREVIEW_ROW = 140; const size_t PREVIEW_COL = 140; const float PIXEL_SPACING = 1.5f; const float HALF_ROI_WIDTH = 100.0f; const unsigned int DRAINAGE_TIME = 180000; // 3 minitues } ScanFormWidget::ScanFormWidget(QWidget* parent) : TabFormWidget(parent) , mPatInf(new PatientInformationForm(this)) , mAccountButton(new QToolButton(this)) , mShutdownButton(new QToolButton(this)) , mWorklistButton(new QToolButton(this)) , mStartScanButton(new QToolButton(this)) , mDrainageButton(new QToolButton(this)) , mXYLabel(new CoordinateXYWidget(this)) , mZLabel(new CoordinateZWidget(this)) , mScanProcessLabel(new QLabel(this)) , mDrainageTimer(new QTimer(this)) { auto commandlayout = new QHBoxLayout(ui->commandWidget); initCommandWidget(commandlayout); //initScanControlBar(commandlayout); initScanContent(); initEvents(); mDrainageTimer->setSingleShot(true); connect(mDrainageTimer, &QTimer::timeout, this, [this]() { mDrainageButton->click(); }); } void ScanFormWidget::initCommandWidget(QHBoxLayout *layout) { bool anonymousMode = JsonObject::Instance()->getAnonymousMode(); mAccountButton->setObjectName("btnAccount"); mAccountButton->setText(tr("Account")); layout->addWidget(mAccountButton); mShutdownButton->setObjectName("btnShutDown"); mShutdownButton->setText(tr("ShutDown")); layout->addWidget(mShutdownButton); mWorklistButton->setObjectName("btnWorklist"); mWorklistButton->setText(tr("Worklist")); mWorklistButton->setEnabled(!anonymousMode); layout->addWidget(mWorklistButton); mStartScanButton->setObjectName("btnScan"); mStartScanButton->setText(tr("Start Scan")); layout->addWidget(mStartScanButton); mStartScanButton->setEnabled(false); mStartScanButton->setCheckable(true); layout->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding)); addVerticalLine(layout); mDrainageButton->setObjectName("btnDrainage"); mDrainageButton->setCheckable(true); mDrainageButton->setText(tr("Drainage")); layout->addWidget(mDrainageButton); connect(mDrainageButton, &QToolButton::clicked, [=](bool aSatus) { //Drainage if(aSatus && DialogManager::Default()->requestAlertMessage(tr("Make sure to open the drain valve ?"), DialogButtonMode::OkAndCancel, tr("Confirm Drainage")) == QDialog::Rejected) { mDrainageButton->setChecked(!aSatus); return; } mDrainageButton->setEnabled(false); if(aSatus == true) { mDrainageTimer->start(DRAINAGE_TIME); QString code = "1"; mDrainageButton->setText(tr("Drainaging")); EventCenter::Default()->triggerEvent(RequestDrainage, nullptr, (QObject*)(&code)); LOG_USER_OPERATION("Perform Drainage"); } else { mDrainageTimer->stop(); QString code = "0"; mDrainageButton->setText(tr("Drainage")); EventCenter::Default()->triggerEvent(RequestDrainage, nullptr, (QObject*)(&code)); LOG_USER_OPERATION("Stop Drainage"); } }); connect(DeviceManager::Default(), &DeviceManager::startPumpControlResult, [this](bool aIsSucessful) { mDrainageButton->setEnabled(true); if(!aIsSucessful) { mDrainageTimer->stop(); bool isChecked = mDrainageButton->isChecked(); mDrainageButton->setChecked(!isChecked); if(isChecked) { mDrainageButton->setText(tr("Drainage")); } else { mDrainageButton->setText(tr("Drainaging")); } } }); connect(mAccountButton, &QToolButton::clicked, DialogManager::Default(),&DialogManager::requestEditSelfAccount); connect(mShutdownButton, &QToolButton::clicked, []() { if(DialogManager::Default()->requestAlertMessage(QString(tr("Shut down now ?")), DialogButtonMode::OkAndCancel,tr("Shut Down")) == QDialog::Accepted) { LOG_USER_OPERATION("Shut Down") EventCenter::Default()->triggerEvent(GUIEvents::RequestShutdown, nullptr, nullptr); } }); connect(mWorklistButton, &QToolButton::clicked, [&]() { DialogManager::Default()->requestGetWorkList(); }); connect(EventCenter::Default(), &EventCenter::AnonymousModeChanged, this, &ScanFormWidget::updateDataByAnonymousMode); connect(mStartScanButton, &QToolButton::clicked, [this]() { if(mStartScanButton->isChecked()) { LOG_USER_OPERATION(QString("Start Scan Process, ID: %1").arg(mPatInf->getPatientID())); EventCenter::Default()->triggerEvent(GUIEvents::StartScanProcess, nullptr, nullptr); } else { LOG_USER_OPERATION(QString("Stop Scan Process, ID: %1").arg(mPatInf->getPatientID())); EventCenter::Default()->triggerEvent(GUIEvents::StopScanProcess, nullptr, nullptr); } }); connect(DeviceManager::Default(), &DeviceManager::startAutoLocateResult, [this]() { mWorklistButton->setEnabled(false); mAccountButton->setEnabled(false); mDrainageButton->setEnabled(false); mShutdownButton->setEnabled(false); mStartScanButton->setText(tr("Stop Scan Process")); mScanProcessLabel->setText(getAutoLocateMessage()); }); connect(EventCenter::Default(), &EventCenter::StopScanProcess, [this]() { mWorklistButton->setEnabled(true); mAccountButton->setEnabled(true); mDrainageButton->setEnabled(true); mShutdownButton->setEnabled(true); mStartScanButton->setChecked(false); mStartScanButton->setText(tr("Start Scan")); if(ScanProcessSequence::getInstance()->getScanPositionSize() == 0) { mStartScanButton->setEnabled(false); mPatInf->clear(); } mScanProcessLabel->setText(tr("Please confirm checking patient information to start the process")); }); connect(EventCenter::Default(), &EventCenter::RequestPatientScan, [this]() { mScanProcessLabel->setText(tr("Data scanning, please keep the current position and don't move.")); }); connect(ScanProcessSequence::getInstance(), &ScanProcessSequence::fullScanDataExport, [this]() { mScanProcessLabel->setText(tr("Data exporting, patient can leave the holder")); }); connect(ScanProcessSequence::getInstance(), &ScanProcessSequence::startFullScan, this, &ScanFormWidget::prepareStartFullScan, Qt::QueuedConnection); } void ScanFormWidget::initScanContent() { QHBoxLayout* contentLayout = new QHBoxLayout(ui->contentWidget); contentLayout->addWidget(mPatInf); QWidget* scanProcessWidget = new QWidget(this); scanProcessWidget->setObjectName("ScanProcessWidget"); contentLayout->addWidget(scanProcessWidget); QVBoxLayout* scanProcessLayout = new QVBoxLayout(scanProcessWidget); mScanProcessLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); mScanProcessLabel->setAlignment(Qt::AlignCenter); mScanProcessLabel->setObjectName("ScanProcessInformation"); mScanProcessLabel->setText(tr("Please confirm checking patient information to start the process")); scanProcessLayout->addWidget(mScanProcessLabel); QWidget* displayWidget = new QWidget(this); scanProcessLayout->addWidget(displayWidget); QHBoxLayout* displayLayout = new QHBoxLayout(displayWidget); QWidget* xyWidget = new QWidget(this); xyWidget->setObjectName("broadcastWidget"); QHBoxLayout* xyLayout = new QHBoxLayout(xyWidget); xyLayout->addWidget(mXYLabel); displayLayout->addWidget(xyWidget); QWidget* zWidget = new QWidget(this); zWidget->setObjectName("broadcastWidget"); QHBoxLayout* zLayout = new QHBoxLayout(zWidget); zLayout->addWidget(mZLabel); displayLayout->addWidget(zWidget); } void ScanFormWidget::initScanControlBar(QHBoxLayout *layout) { // connect(mBtnEScan, &QToolButton::clicked, [=]() { // int result = DialogManager::Default()->requestAlertMessage(tr("Please make sure the holder is only contain water!"),DialogButtonMode::OkAndCancel,tr("Confirm Scan")); // if (result != QDialog::Accepted)return; // QString patientInf(mPatInf->getCurrentPatientJsonString(true)); // LOG_USER_OPERATION("Start Empty Scan") // EventCenter::Default()->triggerEvent(RequestEmptyScan, nullptr, (QObject*)(&patientInf)); // }); // connect(mBtnPreview, &QToolButton::clicked, [=]() { // LOG_USER_OPERATION(QString("Start Preview, ID: %1").arg(mPatInf->getPatientID())) // EventCenter::Default()->triggerEvent(RequestPreviewScan, nullptr, nullptr); // }); // connect(mBtnScan, &QToolButton::clicked, [=]() { // if(JsonObject::Instance()->getScanConfirm()) // { // int ret = DialogManager::Default()->requestPatientConfirm(mPatInf->getPatientInformation(),mPatInf->getProtocol()); // if (ret != QDialog::Accepted) return; // } // QString patientInf(mPatInf->getCurrentPatientJsonString(false)); // LOG_USER_OPERATION(QString("Start Scan, ID: %1").arg(mPatInf->getPatientID())) // if (!DeviceManager::Default()->hasValidEmptyScan()){ // QString msg(tr("No refresh data exists, please do Refresh operation first.")); // EventCenter::Default()->triggerEvent(DeviceErrorRaise, nullptr, (QObject*)(&msg)); // return; // } // EventCenter::Default()->triggerEvent(RequestPatientScan, nullptr, (QObject*)(&patientInf)); // }); // connect(mBtnStop, &QToolButton::clicked, [=]() { // LOG_USER_OPERATION("Stop Preview") // EventCenter::Default()->triggerEvent(RequestPreviewStop, nullptr, nullptr); // }); } void ScanFormWidget::protocolChanged(int type) { LOG_USER_OPERATION(QString("Select Laterality %1").arg(type == 0 ? "Left" : "Right")); } void ScanFormWidget::prepareStartFullScan() { ScanPosition position = ScanProcessSequence::getInstance()->topPosition(); mPatInf->setExecuteProtocol(position == ScanPosition::Left); QString patientInf(mPatInf->getCurrentPatientJsonString(false)); LOG_USER_OPERATION(QString("Start Scan, ID: %1").arg(mPatInf->getPatientID())) EventCenter::Default()->triggerEvent(RequestPatientScan, nullptr, (QObject*)(&patientInf)); } void ScanFormWidget::setPreviewing(bool val) { // mBtnPreview->setCheckable(val); // mBtnPreview->setChecked(val); // mBtnPreview->setEnabled(!val); // mBtnEScan->setEnabled(!val); // mBtnScan->setEnabled(!val); mDrainageButton->setEnabled(!val); } void ScanFormWidget::renderLoading() { setPreviewing(true); uchar c_data[PREVIEW_ROW][PREVIEW_COL]; for (auto data_ptr : c_data) { memset(data_ptr, 0, PREVIEW_COL); } QImage img(c_data[0], PREVIEW_COL, PREVIEW_ROW, QImage::Format_Grayscale8); QPixmap pic = QPixmap::fromImage(img).scaledToHeight(800, Qt::SmoothTransformation); QPainter painter(&pic); QPen pen; pen.setStyle(Qt::DashLine); pen.setWidth(3); QFont font("Futura"); font.setPixelSize(26); font.setBold(true); painter.setFont(font); pen.setColor(QColor(255, 255, 0)); painter.setPen(pen); painter.drawText(400 - 13 * 5, 400 + 13, "Loading..."); } void ScanFormWidget::renderPreviewData(const QObject* /*sender*/,const QObject *data) { if (!data)return; auto array = (QByteArray*)data; auto raw_dataptr = (uchar*)array->data(); uchar c_data[PREVIEW_ROW][PREVIEW_COL]; for (auto data_ptr : c_data) { memcpy(data_ptr, raw_dataptr, PREVIEW_COL); raw_dataptr += PREVIEW_COL; } QImage img(c_data[0], PREVIEW_COL, PREVIEW_ROW, QImage::Format_Grayscale8); QPixmap pic = QPixmap::fromImage(img).scaledToHeight(800, Qt::SmoothTransformation); QPainter painter(&pic); QPen pen; pen.setColor(QColor(255, 255, 0, 100)); pen.setStyle(Qt::DashLine); pen.setWidth(3); QFont font("Futura"); font.setPixelSize(26); font.setBold(true); painter.setFont(font); painter.setPen(pen); static int borderSpacing = (int)roundf(((PIXEL_SPACING * (PREVIEW_ROW * 0.5f) - HALF_ROI_WIDTH) * (800.0f / (1.5f * 140.0f)))); painter.drawLine(borderSpacing, borderSpacing, borderSpacing, 800 - borderSpacing); painter.drawLine(borderSpacing + 1, borderSpacing, 800 - borderSpacing, borderSpacing); painter.drawLine(borderSpacing + 1, 800 - borderSpacing, 800 - borderSpacing, 800 - borderSpacing); painter.drawLine(800 - borderSpacing, borderSpacing + 1, 800 - borderSpacing, 800 - borderSpacing - 1); pen.setColor(QColor(255, 255, 0)); painter.setPen(pen); painter.drawText(335,40,QString("Previewing, current frame:%1").arg(++mCurrentFrame)); painter.drawText(borderSpacing + 13, 400 + 13, "L"); painter.drawText(800 - borderSpacing - 30, 400 + 13, "R"); painter.drawText(400 - 13, borderSpacing + 30, "H"); painter.drawText(400 - 13, 800 - borderSpacing - 13, "F"); painter.drawText(borderSpacing + 6, borderSpacing + 30, "ROI"); } void ScanFormWidget::initEvents() { //Events--------------------------------------------------------------- connect(EventCenter::Default(), &EventCenter::PatientSelected, [=](QObject* sender, QObject* data) { if (data) { PatientInformation* patientInfo = (PatientInformation*)data; DialogResult result = DialogManager::Default()->reuqestConfirmStartScan(patientInfo); if(result.ResultCode == QDialog::Accepted) { ScanProtocal protocal = static_cast(result.ResultData.toInt()); mPatInf->setPatientInformation(patientInfo->Copy(), protocal); setScanProtocal(protocal); LOG_USER_OPERATION(QString("Select Patient, ID: %1").arg(patientInfo->ID)) if (JsonObject::Instance()->getMppsOpen() && !patientInfo->SPSID.isEmpty() && patientInfo->MPPSUID.isEmpty()) { MPPSManager::getInstance()->setPatientUID(patientInfo->PatientUID); } mStartScanButton->setEnabled(true); EventCenter::Default()->triggerEvent(SetSelectedPatient, nullptr, patientInfo); mStartScanButton->click(); } // mBtnScan->setEnabled(true); // mBtnEScan->setEnabled(true); // mBtnPreview->setEnabled(true); // mBtnStop->setEnabled(true); } else{ // mBtnScan->setEnabled(false); // mBtnEScan->setEnabled(false); // mBtnPreview->setEnabled(false); // mBtnStop->setEnabled(false); } }); connect(EventCenter::Default(), &EventCenter::ResponseStopPreview, [=](QObject* sender, QObject* data) { setPreviewing(false); }); connect(EventCenter::Default(), &EventCenter::ResponsePreview, this,&ScanFormWidget::renderLoading); connect(EventCenter::Default(), &EventCenter::ResponsePreviewData, this,&ScanFormWidget::renderPreviewData); connect(EventCenter::Default(), &EventCenter::ReloadLanguage, this, &ScanFormWidget::reloadLanguage); connect(EventCenter::Default(), &EventCenter::DeviceErrorRaise, [=](QObject* parent, QObject* msg){ printf("signal:%d\r\n",senderSignalIndex()); }); } void ScanFormWidget::reloadLanguage() { mAccountButton->setText(tr("Account")); mShutdownButton->setText(tr("ShutDown")); mWorklistButton->setText(tr("Worklist")); mStartScanButton->setText(tr("Start Scan")); mScanProcessLabel->setText(tr("Please confirm checking patient information to start the process")); mDrainageButton->isChecked() ? mDrainageButton->setText(tr("Drainaging")) : mDrainageButton->setText(tr("Drainage")); } void ScanFormWidget::updateDataByAnonymousMode() { bool anonymousMode = JsonObject::Instance()->getAnonymousMode(); mWorklistButton->setEnabled(!anonymousMode); } QString ScanFormWidget::getAutoLocateMessage() { ScanPosition position = ScanProcessSequence::getInstance()->topPosition(); switch (position) { case ScanPosition::Left: return tr("Left side scan initiated, auto positioning in progress."); case ScanPosition::Right: return tr("Right side scan initiated, auto positioning in progress."); } return QString(""); } void ScanFormWidget::setScanProtocal(int aProtocal) { ScanProcessSequence::getInstance()->clear(); switch (aProtocal) { case ScanProtocal::LSTAND: ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Right); ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Left); return; case ScanProtocal::RSTAND: ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Left); ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Right); return; case ScanProtocal::LONE: ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Left); return; case ScanProtocal::RONE: ScanProcessSequence::getInstance()->pushPosition(ScanPosition::Right); return; default: return; } } void ScanFormWidget::keyPressEvent(QKeyEvent* aEvent) { switch (aEvent->key()) { case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: case Qt::Key_A: case Qt::Key_B: case Qt::Key_C: case Qt::Key_D: case Qt::Key_E: case Qt::Key_F: case Qt::Key_G: case Qt::Key_H: case Qt::Key_I: case Qt::Key_J: case Qt::Key_K: case Qt::Key_L: case Qt::Key_M: case Qt::Key_N: case Qt::Key_O: case Qt::Key_P: case Qt::Key_Q: case Qt::Key_R: case Qt::Key_S: case Qt::Key_T: case Qt::Key_U: case Qt::Key_V: case Qt::Key_W: case Qt::Key_X: case Qt::Key_Y: case Qt::Key_Z: { WorkListManager::getInstance()->setSearchString(aEvent->text()); break; } case Qt::Key_Enter: case Qt::Key_Return: { QString text = WorkListManager::getInstance()->getSearchString(); EventCenter::Default()->triggerEvent(InputWorkListSearchValue, nullptr, (QObject*)&text); break; } default: break; } QWidget::keyPressEvent(aEvent); }