#include "formcapture.h"
#include "ui_formcapture.h"
#include "mainwindow.h"
#include "qgstreamerplayer.h"

#include <QFileInfo>
#include <QDirIterator>
#include <QCollator>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>

extern SThreadWatchVideoLink v;

FormCapture::FormCapture(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormCapture)
{
    ui->setupUi(this);

    m_pThreadWatchVideoLink = &v;

    m_pDialogSendProgress = NULL;

    m_bExecStopRTSP = false;


    //MainWindow* pMainWindow = MainWindow::GetMainWindow();
    //connect(this, SIGNAL(ExitCapture()), pMainWindow, SLOT(ExitCapture()));

#ifdef _SYOLOV5
#else
    ui->frame_Detection->setVisible(false);
#endif



    ui->verticalScrollBar->SetSlideType(SSlideBar::SLIDE_VERTICAL);
    ui->verticalScrollBar->setRange(0, 299);

    connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(valueChangedScrollBarVertical(int)));
    //connect(this, SIGNAL(SetSlideValue(int)), ui->verticalScrollBar, SLOT(setValue(int)));
    //connect(ui->verticalScrollBar, SIGNAL(actionTriggered(int)), this, SLOT(actionTriggered(int)));
    connect(ui->verticalScrollBar, SIGNAL(SingleDown()), this, SLOT(SingleDown()));
    connect(ui->verticalScrollBar, SIGNAL(SingleUp()), this, SLOT(SingleUp()));


    ui->horizontalScrollBar->SetSlideType(SSlideBar::SLIDE_HORIZONTAL);
    ui->horizontalScrollBar->setRange(0, 299);

    connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(valueChangedScrollBarHorizontal(int)));
    //connect(this, SIGNAL(SetSlideValue(int)), ui->horizontalScrollBar, SLOT(setValue(int)));
    //connect(ui->horizontalScrollBar, SIGNAL(actionTriggered(int)), this, SLOT(actionTriggered(int)));
    connect(ui->horizontalScrollBar, SIGNAL(SingleDown()), this, SLOT(SingleDown()));
    connect(ui->horizontalScrollBar, SIGNAL(SingleUp()), this, SLOT(SingleUp()));



    connect(&m_Timer, SIGNAL(timeout()), this, SLOT(CheckVideoDevice()));
    m_Timer.setInterval(100);

    connect(&m_TimerCaptureInfo, SIGNAL(timeout()), this, SLOT(CheckCaptureTimeInfo()));
    m_TimerCaptureInfo.setInterval(1000);

    connect(&m_TimerCaptureBeepSound, SIGNAL(timeout()), this, SLOT(FinishBeep()));
    m_TimerCaptureBeepSound.setSingleShot(true);
    //m_TimerCaptureBeepSound.setInterval(500);
    m_TimerCaptureBeepSound.setInterval(0);


    connect(&m_TimerCaptureVideo, SIGNAL(timeout()), this, SLOT(VideoStopEnable()));
    m_TimerCaptureVideo.setSingleShot(true);
    //m_TimerCaptureVideo.setInterval(500);
    m_TimerCaptureVideo.setInterval(0);

    connect(&m_TimerCaptureImage, SIGNAL(timeout()), this, SLOT(ImageCaptureEnable()));
    m_TimerCaptureImage.setSingleShot(true);
    //m_TimerCaptureVideo.setInterval(500);
    m_TimerCaptureImage.setInterval(0);

    connect(&m_TimerCaptureSingleShot, SIGNAL(timeout()), this, SLOT(CaptureSingleShot()));
    m_TimerCaptureSingleShot.setInterval(10);
    m_TimerCaptureSingleShot.setSingleShot(true);


    int i=0;
    for(i=0 ; i<3 ; i++)
    {
        FormCaptureImageSelect* pCaptureImageSelect = new FormCaptureImageSelect(this);
        //connect(pCaptureImageSelect, SIGNAL(SingleDown()), this, SLOT(SingleDown()));
        //connect(pCaptureImageSelect, SIGNAL(SingleUp()), this, SLOT(SingleUp()));
        ui->verticalLayout->addWidget(pCaptureImageSelect);

        m_ListFormVerticalImageSelect.push_back(pCaptureImageSelect);
    }

    for(i=0 ; i<5 ; i++)
    {
        FormCaptureImageSelect* pCaptureImageSelect = new FormCaptureImageSelect(this);
        //connect(pCaptureImageSelect, SIGNAL(SingleDown()), this, SLOT(SingleDown()));
        //connect(pCaptureImageSelect, SIGNAL(SingleUp()), this, SLOT(SingleUp()));
        ui->horizontalLayout->addWidget(pCaptureImageSelect);

        m_ListFormHorizontalImageSelect.push_back(pCaptureImageSelect);
    }

    m_nCurrentPos = 0;
    m_nIndexCurrent = 0;

    m_nHandSwitchValue = 0;
    m_nPrevHandSwitchValue = 0;



}

FormCapture::~FormCapture()
{
    //MainWindow* pMainWindow = MainWindow::GetMainWindow();
    //disconnect(this, SIGNAL(ExitCapture()), pMainWindow, SLOT(ExitCapture()));

    int i=0;
    for(i=0 ; i<3 ; i++)
    {
        FormCaptureImageSelect* pCaptureImageSelect = m_ListFormVerticalImageSelect[i];
        SAFE_DELETE(pCaptureImageSelect);
    }
    m_ListFormVerticalImageSelect.clear();

    for(i=0 ; i<5 ; i++)
    {
        FormCaptureImageSelect* pCaptureImageSelect = m_ListFormHorizontalImageSelect[i];
        SAFE_DELETE(pCaptureImageSelect);
    }
    m_ListFormHorizontalImageSelect.clear();

    SAFE_DELETE(ui->widget_SelectImage);

    delete ui;
}

void FormCapture::SingleDown()
{
    WRITE_FUNCTION_LOG();
    int nItem = 20;
    int nIndexCurrent = m_nIndexCurrent;

    //nItem = pListHistoryImage->size();
    int nTotalImage = 0;
    int i=0;

    CommonData* pCommonData = MainWindow::GetCommonData();
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
            if(pCaptureImage->m_bDelete==false)
            {
                nTotalImage++;
            }
        }
        nItem = nTotalImage;
    }
    pCommonData->ReleaseListCaptureImage();

    float fMaxRange = 299;

    int nPageDisplay = 0;
    int nPageTotal = 0;
    int nItemPerPage = m_nItemPerPage;

    SSlideBar* pSlideBar = NULL;

    int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
    if(nDisplayType==SDISPLAY_1280X1024)
    {
        pSlideBar = ui->horizontalScrollBar;
    }
    else if(nDisplayType==SDISPLAY_1920X1080)
    {
        pSlideBar = ui->verticalScrollBar;
    }

    nIndexCurrent += nItemPerPage;
    nPageTotal = ((nItem-1) / nItemPerPage) + 1;
    nPageDisplay = nIndexCurrent / nItemPerPage;

    if(nPageTotal<=1)
    {
        pCommonData->ReleaseListCaptureImage();
        return;
    }

    if(nPageDisplay >= nPageTotal)
    {
        nPageDisplay = nPageTotal - 1;
    }
    nIndexCurrent = nPageDisplay * nItemPerPage;

    if(nIndexCurrent!=m_nIndexCurrent)
    {
        int nCurrentPos;
        nCurrentPos = (int)( (((float)nPageDisplay / (float)(nPageTotal-1)) * fMaxRange) + 0.5f);
        //qDebug() << "PageDisplay: " << nPageDisplay << " PageTotal: " << nPageTotal << " nCurrentPos: " << nCurrentPos;

        pSlideBar->setValue(nCurrentPos);
    }
}

void FormCapture::SingleUp()
{
    WRITE_FUNCTION_LOG();
    int nItem = 20;
    int nIndexCurrent = m_nIndexCurrent;

    int nTotalImage = 0;
    int i=0;
    CommonData* pCommonData = MainWindow::GetCommonData();
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
            if(pCaptureImage->m_bDelete==false)
            {
                nTotalImage++;
            }
        }
        nItem = nTotalImage;
    }
    pCommonData->ReleaseListCaptureImage();

    float fMaxRange = 299;

    int nPageDisplay = 0;
    int nPageTotal = 0;
    int nItemPerPage = m_nItemPerPage;

    SSlideBar* pSlideBar = NULL;

    int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
    if(nDisplayType==SDISPLAY_1280X1024)
    {
        pSlideBar = ui->horizontalScrollBar;
    }
    else if(nDisplayType==SDISPLAY_1920X1080)
    {
        pSlideBar = ui->verticalScrollBar;
    }

    nIndexCurrent -= nItemPerPage;
    nPageTotal = ((nItem-1) / nItemPerPage) + 1;
    nPageDisplay = nIndexCurrent / nItemPerPage;

    if(nPageTotal<=1)
    {
        pCommonData->ReleaseListCaptureImage();
        return;
    }

    if(nPageDisplay < 0)
    {
        nPageDisplay = 0;
    }
    nIndexCurrent = nPageDisplay * nItemPerPage;

    if(nIndexCurrent!=m_nIndexCurrent)
    {
        int nCurrentPos;
        nCurrentPos = (int)( (((float)nPageDisplay / (float)(nPageTotal-1)) * fMaxRange) + 0.5f);
        //qDebug() << "PageDisplay: " << nPageDisplay << " PageTotal: " << nPageTotal << " nCurrentPos: " << nCurrentPos;
        pSlideBar->setValue(nCurrentPos);
    }
}

void FormCapture::on_pushButton_EXIT_clicked()
{
    WRITE_FUNCTION_LOG();
    m_Timer.stop();

    usleep(100*1000);

    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    int nCaptureMode = 0;

    nCaptureMode = pThreadRTSP->GetCaptureMode();
    if(nCaptureMode==1) // Capture Video
    {
        if(ui->pushButton_VID->isEnabled()==true && ui->pushButton_VID->isChecked()==true)
        {
            VideoSaveEnd();
        }
        else
        {
            int a=0;
        }


        ui->pushButton_VID->setChecked(false);
        ui->pushButton_VID->setEnabled(true);
        ui->pushButton_VID->update();

    }

    pThreadRTSP->SetCaptureMode(2); // Background Streaming

    pThreadRTSP->ChangeState(11);

    if(pThreadRTSP->IsWorkingRTSP()==true)
    {
        pThreadRTSP->StopRTSP();
    }

    MainWindow::GetMainWindow()->ExitCapture();
}

QVideoWidget* FormCapture::GetVideoWidget()
{
    return ui->widget_Video;
}

void FormCapture::on_pushButton_ACQ_clicked()
{
    ui->pushButton_ACQ->setDisabled(true);

    CommonData* pCommonData = MainWindow::GetCommonData();
    CAPTURE_IMAGE* pCaptureImage = NULL;
    bool bIsCropMode = (bool)pCommonData->GetCropMode();

    int nWidth = pCommonData->GetVideoWidth();
    int nHeight = pCommonData->GetVideoHeight();
    int nSaveWidth = pCommonData->GetVideoWidth();
    int nSaveHeight = pCommonData->GetVideoHeight();



    QVideoWidget* pVideoWidget = ui->widget_Video;
    pVideoWidget->Lock();
    {
        uint8_t* pData = pVideoWidget->GetCaptureImage();

        //SThreadImageSave* pThread = MainWindow::GetCommonData()->GetThreadCaptureImage();
        //pThread->SetImageCapture(pData, 1920, 1080);

        pCaptureImage = pCommonData->AddCaptureImage(pData, nWidth, nHeight, DISPLAY_IMAGE);
    }
    pVideoWidget->Unlock();

    pCommonData->Beep(true);
    m_TimerCaptureBeepSound.start(250);
    m_TimerCaptureImage.start(10);


    bool bCreateImageFile = false;
    bCreateImageFile = pCommonData->ConvertCaptureImage(pCaptureImage, nSaveWidth, nSaveHeight);
    if(bCreateImageFile==false)
    {
        SAFE_DELETE(pCaptureImage->m_pImage);
        SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
        SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);

        vector<CAPTURE_IMAGE*>::iterator it;
        vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
        {
            for(it=pListCaptureImage->begin() ; it!=pListCaptureImage->end() ; ++it)
            {
                CAPTURE_IMAGE* pImageDisplay = *it;
                if(pImageDisplay==pCaptureImage)
                {
                    pListCaptureImage->erase(it);
                    break;
                }
            }
        }
        pCommonData->ReleaseListCaptureImage();

        SAFE_DELETE(pCaptureImage);
        return;
    }

    m_nCaptureImageCount++;
    m_TimeCapture.restart();


    /*
    if(bIsCropMode==true)
    {
        *pCaptureImage->m_pImage = pCaptureImage->m_pImage->copy(QRect(242, 5, 1376, 992));
        //SAFE_DELETE(pCaptureImage->m_pImageSmall);
        //pCaptureImage->m_pImageSmall = new QImage;
        *pCaptureImage->m_pImageSmall = pCaptureImage->m_pImage->scaled(pCaptureImage->m_pImage->width()/4, pCaptureImage->m_pImage->height()/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).copy();

    }
    */
    SAFE_DELETE(pCaptureImage->m_pImage);
    SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
    SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);


    if(pCaptureImage!=NULL)
    {
        captureImage(pCaptureImage);
    }

}

void FormCapture::captureImage(CAPTURE_IMAGE* pCaptureImage)
{
    WRITE_FUNCTION_LOG();
    ui->horizontalScrollBar->setValue(0);
    CommonData* pCommonData = MainWindow::GetCommonData();
    bool bIsCropMode = (bool)pCommonData->GetCropMode();

    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        int i=0;
        int nIndex = 0;


        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pImageDisplay = (*pListCaptureImage)[i];
            if(pImageDisplay->m_nIndex==-1)
            {
                pImageDisplay->m_DateTime = QDateTime::currentDateTime();

                if(pImageDisplay->m_strImageFilename.size()>0 && pImageDisplay->m_bSaveFile==false)
                {
                    if(bIsCropMode==true)
                    {
                        *pImageDisplay->m_pImage = pImageDisplay->m_pImage->copy(QRect(242, 5, 1376, 992));
                    }
                    SAFE_DELETE(pImageDisplay->m_pImage);
                    SAFE_DELETE(pImageDisplay->m_pImageCaptureRaw);
                    SAFE_ARRAY_DELETE(pImageDisplay->m_pImageCaptureColor);
                }
            }
            pImageDisplay->m_nIndex = i+1;
        }
    }
    pCommonData->ReleaseListCaptureImage();

    UpdateViewer();

}

void FormCapture::captureVideo(CAPTURE_IMAGE* pCaptureImage)
{
    WRITE_FUNCTION_LOG();
    ui->horizontalScrollBar->setValue(0);

    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    if(ui->pushButton_VID->isChecked()==true)
    {
        //Start Video Encoding

        bool bStartVideoCapture = true;

        if(pCommonData->IsAutoVideoCapture()==true)
        {
            if(m_nCaptureImageCount==1)
            {
                bStartVideoCapture = false;
            }
        }

        if(bStartVideoCapture==true)
        {
            pCaptureImage->m_nType = DISPLAY_VIDEO;
            pCommonData->SetEncodingVideo(true);

            /*
            pThreadRTSP->StopRTSP();
            while(pThreadRTSP->IsWorkingRTSP()==true)
            {
                usleep(10);
            }
            usleep(100*1000);
            */

            //pThreadRTSP->SaveFile(pCaptureImage->m_strVideoFilename);


            if(pCaptureImage->m_pImage!=NULL && pCaptureImage->m_strImageFilename.size()>0)
            {
                SAFE_DELETE(pCaptureImage->m_pImage);
                SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
                SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);
            }
        }

    }
    else
    {
        //Stop Video Encoding

        VideoSaveEnd();
    }

    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        int i=0;
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pImageDisplay = (*pListCaptureImage)[i];
            pImageDisplay->m_nIndex = i+1;
        }
    }
    pCommonData->ReleaseListCaptureImage();


    UpdateViewer();
}

void FormCapture::Init()
{
    WRITE_FUNCTION_LOG();
    CommonData* pCommonData = MainWindow::GetCommonData();
    SThreadImageSave* pThreadImageSave = pCommonData->GetThreadCaptureImage();
    //QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    m_bExecStopRTSP = false;
    m_bPrevConnectHDMI = false;
    SetHDMICalbeConnect(m_bPrevConnectHDMI);

    m_bEncodingVideo = false;
    m_nCaptureImageCount = 0;
    m_bSendBackground = false;
    m_bAutoVideoCapture = false;

    ui->horizontalSlider_Hue->hide();
    ui->horizontalSlider_Saturation->hide();

    ui->horizontalSlider_Hue->setRange(0, 100);
    ui->horizontalSlider_Saturation->setRange(0, 100);

    ui->horizontalSlider_Hue->setValue(50);
    ui->horizontalSlider_Saturation->setValue(50);

    m_bDisconnectCheck = false;

    ui->pushButton_ACQ->setEnabled(true);

    /*
    if(pCommonData->IsAutoVideoCapture()==true)
    {
        ui->pushButton_VID->setChecked(true);
        ui->pushButton_VID->setDisabled(true);
    }
    else
    {
    */
        ui->pushButton_VID->setChecked(false);
        ui->pushButton_VID->setEnabled(true);
    //}



    int i=0;
    for(i=0 ; i<3 ; i++)
    {
        FormCaptureImageSelect* pWidget = m_ListFormVerticalImageSelect[i];
        pWidget->SetCaptureImage(NULL);
    }

    for(i=0 ; i<5 ; i++)
    {
        FormCaptureImageSelect* pWidget = m_ListFormHorizontalImageSelect[i];
        pWidget->SetCaptureImage(NULL);
    }


    //pCommonData->ClearCaptureImage();
    pThreadImageSave->ClearCaptureSaveToFile();
    pThreadImageSave->ClearMissCapture();
    pThreadImageSave->ChangeState(0x0);
    if(pCommonData->IsActiveDetect()==true)
    {
        pThreadImageSave->SetExecuteDetect(true);
    }
    if(pCommonData->IsUseUSBBackup()==true)
    {
        pThreadImageSave->SetExecuteBackup(true);
    }

    pCommonData->SetEncodingVideo(false);

    ui->frame_horizontalScrollBar->hide();

    ui->frame_verticalScrollBar->hide();

    ui->widget_Video->Init();

    ui->label_LastCapture->hide();

    ui->horizontalScrollBar->setRange(0, 299);
    ui->horizontalScrollBar->setValue(0);


    ui->checkBox_Detection->setChecked(false);
    pCommonData->SetActiveDetect(false);

    ui->widget_SelectImage->Init();


    m_Timer.start();
    m_TimerCaptureInfo.start();

    ACQUISITION_INFO* pAcquisitionInfo = pCommonData->GetAcquisitionInfo();
    SDATA_PATIENT* pInfoPatient = pAcquisitionInfo->GetPatientInfo();

    if(pInfoPatient!=NULL)
    {
        ui->info_ID->setText(pInfoPatient->strPatientID);
        ui->info_Name->setText(pInfoPatient->strPatientName);
        QString strStudyInfo;
        strStudyInfo = pAcquisitionInfo->GetStudyInfo()->strStudyDescription;
        strStudyInfo += "  ";
        strStudyInfo += pAcquisitionInfo->GetPatientInfo()->strPatientAge;
        strStudyInfo += "  ";
        strStudyInfo += pAcquisitionInfo->GetPatientInfo()->strPatientSex;
        ui->label_StudyDescription->setText(strStudyInfo);
        QString strPatientBirthDate = pInfoPatient->strPatientBirthDate;
        if(strPatientBirthDate.size()==8)
        {
            strPatientBirthDate.insert(6, '/');
            strPatientBirthDate.insert(4, '/');
        }
        ui->info_Birth->setText(strPatientBirthDate);
    }
    pCommonData->ReleaseAcquisitionInfo();

    int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
    if(nDisplayType==SDISPLAY_1280X1024)
    {
        m_nItemPerPage = 5;
    }
    else
    {
        m_nItemPerPage = 3;
    }



    int nCountCaptureImage = 0;
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        nCountCaptureImage = pListCaptureImage->size();
    }
    pCommonData->ReleaseListCaptureImage();

    if(nCountCaptureImage>0)
    {
        UpdateViewer();
    }

    m_nHandSwitchValue = 0;
    m_nPrevHandSwitchValue = 0;

    qDebug() << "271 Port Timer Start";
    //m_TimeHandSwitchOn.start();

    m_TimeCapture = QElapsedTimer();



    m_nIndexCurrent = 0;

    if(pCommonData->IsAutoCaptureSendDICOM()==true)
    {
        SThreadSendDICOM* pThreadSendDICOM = pCommonData->GetThreadSendDICOM();

        if(pThreadSendDICOM!=NULL)
        {
            pThreadSendDICOM->Init();
            pThreadSendDICOM->SetAutoSendImage();
            m_bSendBackground = true;
        }
        else
        {
            m_bSendBackground = false;
        }



        /*
        pThreadSendDICOM->SetAutoSendImage();

        if(m_pDialogSendProgress!=NULL)
        {

            delete m_pDialogSendProgress;
            m_pDialogSendProgress = NULL;
        }
        */
    }



    //bool bIsConnectHDMI = pCommonData->IsConnectHDMI();
    //SetHDMICalbeConnect(bIsConnectHDMI);




    m_pThreadWatchVideoLink->ChangeState(1);


    usleep(500*1000);
    m_TimerStartPipeLine.restart();

    m_bDisconnectCheck = false;
    m_bAutoVideoCapture = false;
    m_bEncodingVideo = false;
    m_bPrevConnectHDMI = false;

    if(pCommonData->IsAutoVideoCapture()==true)
    {
        m_bEncodingVideo = true;
    }

    //qDebug() << "FormCapture: ChangeState(0)";
    //pThreadRTSP->ChangeState(0);
    qDebug() << "FormCapture: INIT Finished!";

}

void FormCapture::ExitCapture()
{
    WRITE_FUNCTION_LOG();

    m_pThreadWatchVideoLink->ChangeState(0);

    MainWindow* pMainWindow = MainWindow::GetMainWindow();
    CommonData* pCommonData = MainWindow::GetCommonData();
    SDatabase* pDatabase = NULL;

    int i=0;
    SThreadSendDICOM* pThreadSendDICOM = pCommonData->GetThreadSendDICOM();

    QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    if(pCommonData->IsAutoCaptureSendDICOM()==true)
    {
        m_bSendBackground = false;
        int nTestCount = 0;
        if(pThreadSendDICOM->GetCurrentState()&0x20)
        {
            pThreadSendDICOM->SetExitAutoSend();
        }

        while(pThreadSendDICOM->GetCurrentState()&0x20 && nTestCount<500)
        {
            usleep(1000*2);
            nTestCount++;
        }

        if(nTestCount>=500)
        {
            int a=0;
        }

        vector<QString> listAutoSendCompleteFile = pThreadSendDICOM->GetListAutoSendCompleteFile();
        if (!listAutoSendCompleteFile.empty())
        {
            // 1. 이 작업을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
            SUTIL::SDatabase db(QString("AutoSendUpdate_%1").arg(reinterpret_cast<quintptr>(this)));
            if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
            {
                // 2. 지역 인스턴스 'db'를 사용하여 트랜잭션을 관리합니다.
                db.BeginTransaction();
                for (const QString& strAutoSendCompleteFile : listAutoSendCompleteFile)
                {
                    // 3. 이미 안전하게 리팩토링된 SendUpdateAcquisitionTemp 함수를 호출합니다.
                    db.SendUpdateAcquisitionTemp(strAutoSendCompleteFile);
                }
                db.Commit();
            }
            else
            {
                qWarning() << "DB open failed for auto send update.";
            }
            // 'db' 객체는 스코프가 끝나면 자동으로 소멸됩니다.
        }
    }

    SThreadImageSave* pThreadImageSave = pCommonData->GetThreadCaptureImage();
    if(pCommonData->IsActiveDetect()==true)
    {
        pThreadImageSave->SetExecuteDetect(false);
    }
    if(pCommonData->IsUseUSBBackup()==true)
    {
        pThreadImageSave->SetExecuteBackup(false);
        while(pThreadImageSave->IsExecuteBackup()==true)
        {
            usleep(100*1000);
        }
    }

    WriteDatabaseListCapture();
    usleep(100*1000);

    // 1. 이 작업을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
    SUTIL::SDatabase db(QString("MergeTempData_%1").arg(reinterpret_cast<quintptr>(this)));
    if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
    {
        // 2. 단일 함수 호출로 '병합'과 '정리' 작업을 모두 수행합니다.
        //    리팩토링된 AddAcquisitionTempToImage 함수는 내부에 트랜잭션과
        //    AcquisitionTemp 테이블 정리 로직을 이미 포함하고 있습니다.
        db.AddAcquisitionTempToImage();
    }
    else
    {
        qWarning() << "DB open failed for merging temp data.";
        // 필요에 따라 오류 처리
    }

    usleep(10*1000);
    //QProcess::execute("sync");

    if(pCommonData->IsAutoExitCaptureSendDICOM()==true)
    {
        vector<QString> listFile;
        ACQUISITION_INFO* pAcquisitionInfo = pCommonData->GetAcquisitionInfo();
        int nStudyIndex = pAcquisitionInfo->GetSeriesInfo()->nStudyIndex;
        pCommonData->ReleaseAcquisitionInfo();


        if(pThreadSendDICOM!=NULL)
        {
            bool bExecuteSend = true;

            bool bAutoRetry = true;

            int nTryCount = 0;

            bool bCacheWriteSuccess = false;

            {
                // 1. 재시도 루프에 진입하기 전에 지역 DB 인스턴스를 생성하고 연결합니다.
                //    이렇게 하면 루프 안에서 불필요하게 연결을 반복하지 않아 효율적입니다.
                SUTIL::SDatabase db(QString("CacheWriteTask_%1").arg(reinterpret_cast<quintptr>(this)));
                if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
                {
                    // 2. 최대 3번까지, 그리고 성공하지 못했을 경우에만 루프를 실행합니다.
                    for (int i = 0; i < 3 && !bCacheWriteSuccess; i++)
                    {
                        // 3. 새로운 CacheWrite API를 호출합니다. 이제 bool 값을 반환합니다.
                        bCacheWriteSuccess = db.CacheWrite();

                        // 4. 실패했을 경우에만 대기 후 재시도합니다.
                        if (!bCacheWriteSuccess)
                        {
                            qWarning() << "CacheWrite failed. Retrying... (" << i + 1 << "/3)";
                            QThread::msleep(100); // 100ms 대기 후 재시도
                        }
                    }
                }
                else
                {
                    qWarning() << "DB open failed for CacheWrite task.";
                }

                // 최종 성공 여부에 따라 후속 처리
                if (bCacheWriteSuccess)
                {
                    qDebug() << "Cache was successfully written to disk.";
                }
                else
                {
                    qCritical() << "Failed to write cache to disk after 3 attempts.";
                }
            }




            QThread::usleep(100*1000);

            {
                // 1. 이 작업을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
                SUTIL::SDatabase db(QString("GetSendListTask_%1").arg(reinterpret_cast<quintptr>(this)));
                if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
                {
                    // 2. 지역 인스턴스 'db'를 사용하여 안전하게 함수를 호출합니다.
                    //    GetSendList 함수는 vector<QString>을 직접 반환합니다.
                    listFile = db.GetSendList(nStudyIndex);
                }
                else
                {
                    qWarning() << "DB open failed for GetSendList task.";
                    // 필요에 따라 오류 처리
                }
            }


            if(listFile.size()==0)
            {
                bExecuteSend = false;
            }

            while(bExecuteSend==true)
            {
                while(pThreadSendDICOM->GetCurrentState()&0x40)
                {
                    usleep(100*1000);
                }

                if(nTryCount>1)
                {
                    bAutoRetry = false;
                }

                int nSendCount = 0;
                {
                    // 포인터가 아닌 값 타입의 리스트. 이 변수는 함수로부터 결과를 직접 받습니다.
                    QList<QStringList> listResponse;

                    // 1. 이 작업을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
                    SUTIL::SDatabase db(QString("GetExitSendListInfo_Task_%1").arg(reinterpret_cast<quintptr>(this)));
                    if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
                    {
                        // 2. 새로운 API를 호출합니다. 함수가 직접 결과 리스트 "값"을 반환합니다.
                        listResponse = db.GetExitSendListInfo(nStudyIndex);

                        // 3. count는 반환된 리스트의 .size()를 통해 얻습니다.
                        nSendCount = listResponse.size();
                    }
                    else
                    {
                        qWarning() << "DB open failed for GetExitSendListInfo task.";
                        // 필요에 따라 오류 처리
                    }

                    pThreadSendDICOM->SetSendImageList(listResponse);
                }


                if(m_pDialogSendProgress!=NULL)
                {
                    delete m_pDialogSendProgress;
                }
                m_pDialogSendProgress = new DialogProgress(this);

                m_pDialogSendProgress->Init(1);
                m_pDialogSendProgress->SetAutoRetryDICOMSend(bAutoRetry);
                m_pDialogSendProgress->exec();

                {
                    vector<QString> listImageSendCompleteFile = pThreadSendDICOM->GetListImageSendCompleteFile();

                    if (!listImageSendCompleteFile.empty())
                    {
                        // 1. 이 작업을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
                        SUTIL::SDatabase db(QString("ImageSendUpdate_%1").arg(reinterpret_cast<quintptr>(this)));
                        if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
                        {
                            // 2. 새로운 이름의 트랜잭션 함수를 사용합니다.
                            db.BeginTransaction();
                            for (const QString& strImageSendCompleteFile : listImageSendCompleteFile)
                            {
                                // 3. 지역 인스턴스 'db'를 통해 안전하게 함수를 호출합니다.
                                db.SendUpdate(strImageSendCompleteFile);
                            }
                            db.Commit();
                        }
                        else
                        {
                            qWarning() << "DB open failed for image send update.";
                        }
                    }
                }


                int nRet = m_pDialogSendProgress->result();

                if(m_pDialogSendProgress->IsError()==false)
                {
                    bExecuteSend = false;
                }
                else
                {
                    if(nRet==QDialog::Rejected)
                    {
                        bExecuteSend = false;
                    }
                }

                if(m_pDialogSendProgress!=NULL)
                {
                    delete m_pDialogSendProgress;
                    m_pDialogSendProgress = NULL;
                }

                //SDatabase::DeleteListReponse(listResponse);

                nTryCount++;
            }
        }
    }

    if(pCommonData->IsUseNetworkBackupVideo()==true)
    {
        vector<QString>* pListExport = pCommonData->GetExportList();

        vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
        {

            for(i=pListCaptureImage->size()-1 ; i>=0 ; i--)
            {
                CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
                if(pCaptureImage->m_nType==DISPLAY_VIDEO)
                {
                    QString strImageFilename = pCaptureImage->m_strImageFilename;
                    QFileInfo fileCheck(strImageFilename);
                    if(fileCheck.exists()==true)
                    {
                        QString strPath = fileCheck.path();
                        QString strFilename = fileCheck.fileName();

                        QStringList filter;
                        if(strFilename.size()>0)
                        {
                            strFilename = strFilename.left(strFilename.size()-4);
                            filter << strFilename + QString("*") + MOVIE_FILE_EXTENSION;
                        }

                        QDirIterator it(strPath, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::NoIteratorFlags);
                        QStringList listMovieFile;
                        while(it.hasNext()==true)
                        {
                            QString strVideoFilename = it.next();
                            listMovieFile << strVideoFilename;
                            pListExport->push_back(strVideoFilename);
                        }
                    }


                }
            }
        }
        pCommonData->ReleaseListCaptureImage();


        if(pListExport->size()>0)
        {
            /*
            SambaClient* pSambaClient = MainWindow::GetCommonData()->GetSambaClient();

            bool bMount = pSambaClient->IsMount();
            if(bMount==true)
            {
                BackupNetworkShareFolder("");
            }
            */
            BackupNetworkShareFolder("");

            pListExport->clear();
        }
    }

    m_TimerCaptureInfo.stop();
    ui->widget_Video->Exit();

    m_nHandSwitchValue = 0;
    m_nPrevHandSwitchValue = 0;




    //QProcess::execute("sync");

    //pCommonData->GetThreadCaptureImage()->ChangeState(0);
    pCommonData->ClearCaptureImage();

    if(pThreadRTSP->IsWorkingRTSP()==true)
    {
        pThreadRTSP->ChangeState(11);
        pThreadRTSP->StopRTSP();
        usleep(10*1000);
    }

    QElapsedTimer nCheckTime;
    nCheckTime.restart();
    while(pThreadRTSP->IsWorkingRTSP()==true)
    {
        usleep(100);
        if(nCheckTime.elapsed() > 7*1000)
        {
            pMainWindow->SetDisplayError("Cannot Disconnect VideoLink!");
            break;
        }
    }
}

void FormCapture::on_pushButton_VID_clicked()
{
    WRITE_FUNCTION_LOG();

    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    if(pThreadRTSP->IsVideoLink()==false || pThreadRTSP->IsWorkingRTSP()==false)
    {
        ui->pushButton_VID->setChecked(false);
        return;
    }

    if(pCommonData->IsEncodingVideo()==false)
    {
        if(pThreadRTSP->IsVideoLink()==true && pThreadRTSP->IsWorkingRTSP()==true)
        {
            m_nCaptureImageCount++;
            QString strVideoFilename = pCommonData->GetNewFilename(DISPLAY_VIDEO);
            pThreadRTSP->SetCaptureMode(1);
            pThreadRTSP->SaveFile(strVideoFilename);

            VideoButtonChange(true);
            m_TimeCaptureVideo.restart();
            m_bEncodingVideo = true;
        }
        else
        {
            ui->pushButton_VID->setChecked(false);
            m_bEncodingVideo = false;
        }
    }
    else
    {
        //m_Timer.stop();

        VideoSaveEnd();

        VideoButtonChange(false);
        m_bEncodingVideo = false;
    }
    m_bDisconnectCheck = false;


}

void FormCapture::VideoSaveEnd()
{
    // --- 1. 기본 준비 (기존 코드와 동일) ---
    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pThreadRTSP = pCommonData->GetThreadRTSP();

    pThreadRTSP->SaveEnd();
    pThreadRTSP->SetCaptureMode(0);
    pCommonData->SetEncodingVideo(false);

    QString strVideoFile = pThreadRTSP->GetVideoFilename(); // 예: /path/to/video_12345.mp4

    // --- 2. DB 인스턴스 생성 및 트랜잭션 시작 ---
    SUTIL::SDatabase db(QString("VideoSaveEnd_%1").arg(reinterpret_cast<quintptr>(this)));
    if (db.OpenDatabase("/home/birdhead/test.db") != 0) {
        qWarning() << "DB open failed in VideoSaveEnd.";
        return;
    }

    if (!db.BeginTransaction()) {
        qWarning() << "Failed to begin transaction in VideoSaveEnd.";
        return;
    }

    // --- 3. 파일 시스템에서 분할된 비디오 파일 목록 가져오기 (기존 코드와 동일) ---
    QFileInfo fi(strVideoFile);
    QString strPath = fi.path();
    QList<QString> listFileLocation;

    QString strBaseFilename = fi.fileName();
    if (strBaseFilename.contains(MOVIE_FILE_EXTENSION)) {
        strBaseFilename.replace(MOVIE_FILE_EXTENSION, "");
        // RTSP 스레드가 저장하는 파일 이름 패턴에 맞게 와일드카드 적용
        // 예: "video_12345_*"
        QString strFilenamePattern = strBaseFilename + "*" + MOVIE_FILE_EXTENSION;

        QDirIterator itDir(strPath, {strFilenamePattern}, QDir::Files);
        while(itDir.hasNext()) {
            listFileLocation.push_back(itDir.next());
        }

        // 파일 이름을 숫자로 인식하여 올바르게 정렬
        QCollator collator;
        collator.setNumericMode(true);
        std::sort(listFileLocation.begin(), listFileLocation.end(), collator);
    }

    // --- 4. 데이터베이스 작업 ---
    bool bSuccess = true;
    QList<QStringList*> listResult;

    // LIKE 절에 사용할 검색용 파일 경로 (확장자 제거)
    QString searchFileLocation = strVideoFile;
    searchFileLocation.replace(MOVIE_FILE_EXTENSION, "");

    QString selectQuery = "SELECT `SeriesIndex`, `ImageNumber`, `ImageInstanceUID`, `StudyIndex`, `AcquisitionDate`, `AcquisitionTime`, "
                          "`ContentDate`, `ContentTime`, `AcquisitionNumber`, `InstanceNumber`, `PatientOrientation`, `ImageLaterality`, "
                          "`ImageComments` FROM AcquisitionTemp WHERE FileLocation LIKE ? AND FileType=1;";

    db.ExecuteQuery(selectQuery, { QString("%%1%").arg(searchFileLocation) }, listResult);

    if (!listResult.isEmpty())
    {
        // 4-1. 원본 비디오 레코드 정보 파싱
        const QStringList* pListData = listResult.at(0);
        QString strSeriesIndex        = pListData->at(0);
        QString strImageNumber        = pListData->at(1);
        QString strImageInstanceUID   = pListData->at(2);
        QString strStudyIndex         = pListData->at(3);
        QString strAcquisitionDate    = pListData->at(4);
        QString strAcquisitionTime    = pListData->at(5);
        QString strContentDate        = pListData->at(6);
        QString strContentTime        = pListData->at(7);
        QString strAcquisitionNumber  = pListData->at(8);
        QString strInstanceNumber     = pListData->at(9);
        QString strPatientOrientation = pListData->at(10);
        QString strImageLaterality    = pListData->at(11);
        QString strImageComments      = pListData->at(12);

        QSqlDatabase qdb = QSqlDatabase::database(db.connectionName());

        // 4-2. 루프 밖에서 쿼리 미리 준비 (성능 향상)
        QSqlQuery updateQuery(qdb);
        updateQuery.prepare("UPDATE AcquisitionTemp SET FileLocation = ? WHERE FileLocation = ?;");

        QSqlQuery insertQuery(qdb);
        insertQuery.prepare("INSERT INTO AcquisitionTemp(`SeriesIndex`, `ImageNumber`, `ImageInstanceUID`, `FileLocation`, `StudyIndex`, "
                            "`AcquisitionDate`, `AcquisitionTime`, `ContentDate`, `ContentTime`, `AcquisitionNumber`, `InstanceNumber`, "
                            "`PatientOrientation`, `ImageLaterality`, `ImageComments`, `FileType`) "
                            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1);");

        // 4-3. 파일 목록을 순회하며 DB 업데이트 또는 삽입
        for (int i = 0; i < listFileLocation.size(); ++i)
        {
            QString strTmpFileLocation = listFileLocation.at(i);
            if (i == 0) {
                // 첫 번째 파일은 기존 레코드의 파일 경로를 업데이트
                updateQuery.addBindValue(strTmpFileLocation);
                updateQuery.addBindValue(strVideoFile); // 원본 임시 파일 경로
                if (!updateQuery.exec()) {
                    qWarning() << "VideoSaveEnd UPDATE failed:" << updateQuery.lastError().text();
                    bSuccess = false;
                    break;
                }
            } else {
                // 두 번째 이후 파일들은 새로운 레코드로 삽입
                QString strNewImageInstanceUID = QString("%1.%2").arg(strImageInstanceUID).arg(i + 1);

                insertQuery.addBindValue(strSeriesIndex.toInt());
                insertQuery.addBindValue(strImageNumber.toInt());
                insertQuery.addBindValue(strNewImageInstanceUID);
                insertQuery.addBindValue(strTmpFileLocation);
                insertQuery.addBindValue(strStudyIndex.toInt());
                insertQuery.addBindValue(strAcquisitionDate);
                insertQuery.addBindValue(strAcquisitionTime);
                insertQuery.addBindValue(strContentDate);
                insertQuery.addBindValue(strContentTime);
                insertQuery.addBindValue(strAcquisitionNumber.toInt());
                insertQuery.addBindValue(strInstanceNumber.toInt());
                insertQuery.addBindValue(strPatientOrientation);
                insertQuery.addBindValue(strImageLaterality);
                insertQuery.addBindValue(strImageComments);

                if (!insertQuery.exec()) {
                    qWarning() << "VideoSaveEnd INSERT failed:" << insertQuery.lastError().text();
                    bSuccess = false;
                    break;
                }
            }
        }
    }

    SUTIL::SDatabase::DeleteListReponse(listResult);

    // --- 5. 트랜잭션 완료 ---
    if (bSuccess) {
        db.Commit();
        qDebug() << "VideoSaveEnd: Successfully processed" << listFileLocation.size() << "video files.";
    } else {
        db.Rollback();
        qWarning() << "VideoSaveEnd: An error occurred. Transaction rolled back.";
    }
    // 이 함수의 끝에서 'db' 객체는 자동으로 소멸됩니다.
}

void FormCapture::VideoButtonChange(bool bEncodingVideo)
{
    if(bEncodingVideo==true)
    {
        ui->pushButton_VID->setDisabled(true);
        ui->pushButton_VID->setChecked(true);
        ui->pushButton_VID->update();

        m_TimeCapture.restart();
        m_TimerStartPipeLine.restart();

        m_bAutoVideoCapture = false;

        m_TimerCaptureVideo.start(3000);
    }
    else
    {
        ui->pushButton_VID->setChecked(false);
        ui->pushButton_VID->update();
        update();

        ui->pushButton_VID->setDisabled(true);
        m_TimerCaptureVideo.start(3000);

        //m_Timer.start();
        m_TimerStartPipeLine.restart();
    }
}


void FormCapture::valueChangedScrollBarVertical(int value)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(value));
    int nTotalImage = 0;
    int i=0;

    CommonData* pCommonData = MainWindow::GetCommonData();
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
            if(pCaptureImage->m_bDelete==false)
            {
                nTotalImage++;
            }
        }
    }
    pCommonData->ReleaseListCaptureImage();


    int nItem = nTotalImage;

    float fMaxItem = nItem;
    float fMaxRange = 299;
    int nItemIndex = (((float)value/fMaxRange) * fMaxItem + 0.5f);

    int nPageDisplay = 0;
    int nPageTotal = 0;
    int nItemPerPage = m_nItemPerPage;

    int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
    if(nDisplayType==SDISPLAY_1280X1024)
    {

    }
    else if(nDisplayType==SDISPLAY_1920X1080)
    {

    }

    nPageTotal = ((nItem-1) / nItemPerPage) + 1;
    nPageDisplay = ( ((float)value / fMaxRange) * (nPageTotal-1) + 0.5f );

    if(nPageTotal<=1)
    {
        return;
    }

    if(nPageDisplay >= nPageTotal)
    {
        nPageDisplay = nPageTotal-1;
    }

    nItemIndex = nPageDisplay * nItemPerPage;

    m_nCurrentPos = value;

    if(m_nIndexCurrent!=nItemIndex)
    {
        m_nIndexCurrent = nItemIndex;
        UpdateViewer();
    }
}

void FormCapture::valueChangedScrollBarHorizontal(int value)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(value));
    int nTotalImage = 0;
    int i=0;
    //qDebug() << value;
    CommonData* pCommonData = MainWindow::GetCommonData();
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
            if(pCaptureImage->m_bDelete==false)
            {
                nTotalImage++;
            }
        }
    }
    pCommonData->ReleaseListCaptureImage();

    int nItem = nTotalImage;

    float fMaxItem = nItem;
    float fMaxRange = 299;
    int nItemIndex = (((float)value/fMaxRange) * fMaxItem + 0.5f);

    int nPageDisplay = 0;
    int nPageTotal = 0;
    int nItemPerPage = m_nItemPerPage;

    int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
    if(nDisplayType==SDISPLAY_1280X1024)
    {

    }
    else if(nDisplayType==SDISPLAY_1920X1080)
    {

    }

    nPageTotal = ((nItem-1) / nItemPerPage) + 1;
    nPageDisplay = ( ((float)value / fMaxRange) * (nPageTotal-1) + 0.5f );

    if(nPageTotal<=1)
    {
        return;
    }

    if(nPageDisplay >= nPageTotal)
    {
        nPageDisplay = nPageTotal-1;
    }

    nItemIndex = nPageDisplay * nItemPerPage;

    m_nCurrentPos = value;

    if(m_nIndexCurrent!=nItemIndex)
    {
        m_nIndexCurrent = nItemIndex;
        UpdateViewer();
    }
}

void FormCapture::UpdateViewer()
{
    WRITE_FUNCTION_LOG();
    int nIndex = 0;
    int nDisplayNumber = m_nItemPerPage;
    int i=0;

    int nTotalImage = 0;

    CommonData* pCommonData = MainWindow::GetCommonData();

    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        for(i=0 ; i<pListCaptureImage->size() ; i++)
        {
            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[i];
            if(pCaptureImage->m_bDelete==false)
            {
                nTotalImage++;
            }
        }

        int nDisplayType = MainWindow::GetCommonData()->GetDisplayType();
        if(nDisplayType==SDISPLAY_1280X1024)
        {
            for(i=0 ; i<nDisplayNumber ; i++)
            {
                FormCaptureImageSelect* pForm = NULL;

                pForm = m_ListFormHorizontalImageSelect[nIndex];

                int nDisplayIndex = (nTotalImage-1) - (m_nIndexCurrent+nIndex);
                if(nDisplayIndex<pListCaptureImage->size() && nDisplayIndex>=0)
                {
                    CAPTURE_IMAGE* pImageSelect = NULL;
                    if(pListCaptureImage->size() > nDisplayIndex)
                    {
                        int j=0;
                        int nIndexTest = 0;
                        for(j=0 ; j<pListCaptureImage->size() ; j++)
                        {
                            CAPTURE_IMAGE* pCaptureImage = (*pListCaptureImage)[j];
                            if(pCaptureImage->m_bDelete==false)
                            {
                                if(nDisplayIndex==nIndexTest)
                                {
                                    pImageSelect = pCaptureImage;
                                    pImageSelect->m_nIndex = nIndexTest + 1;
                                    break;
                                }
                                nIndexTest++;
                            }
                        }
                        //pImageSelect = (*pListCaptureImage)[nDisplayIndex];
                    }

                    pForm->SetCaptureImage(pImageSelect);
                }
                else
                {
                    pForm->SetCaptureImage(NULL);
                }

                pForm->update();
                nIndex++;
            }

            ui->verticalLayoutWidget->show();
            ui->verticalLayout->update();
            if(pListCaptureImage->size()>m_nItemPerPage)
            {
                ui->frame_horizontalScrollBar->show();
            }
            else
            {
                ui->frame_horizontalScrollBar->hide();
            }
        }
        else if(nDisplayType==SDISPLAY_1920X1080)
        {
            for(i=0 ; i<nDisplayNumber ; i++)
            {
                FormCaptureImageSelect* pForm = NULL;

                pForm = m_ListFormVerticalImageSelect[nIndex];

                int nDisplayIndex = (nTotalImage-1) - (m_nIndexCurrent+nIndex);
                if(nDisplayIndex<pListCaptureImage->size() && nDisplayIndex>=0)
                {
                    CAPTURE_IMAGE* pImageSelect = NULL;
                    if(pListCaptureImage->size() > nDisplayIndex)
                    {
                        pImageSelect = (*pListCaptureImage)[nDisplayIndex];
                    }

                    pForm->SetCaptureImage(pImageSelect);
                }
                else
                {
                    pForm->SetCaptureImage(NULL);
                }

                pForm->update();
                nIndex++;
            }

            ui->verticalLayoutWidget->show();
            ui->verticalLayout->update();
            if(pListCaptureImage->size()>m_nItemPerPage)
            {
                ui->frame_verticalScrollBar->show();
            }
            else
            {
                ui->frame_verticalScrollBar->hide();
            }
        }
    }
    pCommonData->ReleaseListCaptureImage();




}

void FormCapture::wheelEvent(QWheelEvent *event)
{
    WRITE_FUNCTION_LOG();
    int nDelta = event->delta();
    if(nDelta<0)
    {
        SingleDown();
    }
    else if(nDelta>0)
    {
        SingleUp();
    }
}

void FormCapture::CheckVideoDevice()
{
    QGstreamerPlayer* pPlayer = NULL;
    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pRTSPThread = pCommonData->GetThreadRTSP();
    QVideoWidget* pVideoWidget = ui->widget_Video;
    bool bHDMI = true;
    QElapsedTimer nCheckTime;

    pPlayer = pRTSPThread->GetGstreamerPlayer();
    nCheckTime.start();

    if(pPlayer==NULL)
    {
        usleep(100);
        return;
    }

    bool bPlayerCleanQueue = false;

    //Existing Thread of Video Watching Link
    if(m_pThreadWatchVideoLink!=NULL)
    {
        bHDMI = m_pThreadWatchVideoLink->IsConnectHDMI();

        if(bHDMI==false)
        {
            m_bDisconnectCheck = true;
            if(pRTSPThread->IsVideoLink()==true)
            {
                //bHDMI = true;
            }
        }

        if(bHDMI!=m_bPrevConnectHDMI)
        {
            SetHDMICalbeConnect(bHDMI);

            if(bHDMI==true)
            {
                m_bExecStopRTSP = false;
            }

            m_bPrevConnectHDMI = bHDMI;
            usleep(100);
            return;
        }
    }


    if(m_bEncodingVideo==true)
    {
        if(pRTSPThread->IsWorkingRTSP()==true && pRTSPThread->GetCaptureMode()==1)
        {
            qint64 nTimeEncodeVideo = m_TimeCaptureVideo.elapsed();
            if(nTimeEncodeVideo < 3 * 1000)
            {
                return;
            }

            //Video Disconnected where Encoding
            if(m_bDisconnectCheck==true)
            {
                usleep(100);

                VideoSaveEnd();

                VideoButtonChange(false);
                m_bDisconnectCheck = false;
                m_bEncodingVideo = true;

                bPlayerCleanQueue = true;
            }
        }

    }

    //Save Database when Video Encoding
    if(m_bAutoVideoCapture==false && pRTSPThread->GetCaptureMode()==1)
    {
        if(pRTSPThread->IsWorkingRTSP()==true && pRTSPThread->IsVideoLink()==true)
        {
            int nWidth = 1920;
            int nHeight = 1080;
            CAPTURE_IMAGE* pCaptureImage = NULL;

            m_bAutoVideoCapture = true;
            m_nCaptureImageCount++;
            m_TimeCapture.restart();

            pCommonData->SetEncodingVideo(true);

            QString strVideoFilename = pCommonData->GetThreadRTSP()->GetVideoFilename();

            uint8_t* pData = NULL;

            if(pVideoWidget->Lock()==true)
            {
                pData = pVideoWidget->GetCaptureImage();
            }
            pVideoWidget->Unlock();

            pCaptureImage = pCommonData->AddCaptureImage(pData, nWidth, nHeight, DISPLAY_VIDEO);

            QThread::usleep(10*1000);

            pCaptureImage->m_strVideoFilename = strVideoFilename;

            bool bCreateImageFile = false;
            bCreateImageFile = pCommonData->ConvertCaptureImage(pCaptureImage, nWidth, nHeight);

            pCaptureImage->m_bSaveFile = true;
            SAFE_DELETE(pCaptureImage->m_pImage);
            SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
            SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);

            if(pCaptureImage!=NULL)
            {
                captureVideo(pCaptureImage);
            }
        }
    }

    int nVideoTime = pRTSPThread->GetVideoLinkTime();
    if(pPlayer->IsPipeStart()==true)
    {
        if(nVideoTime>3*1000 && bHDMI==false)
        //if(bHDMI==false)
        {
            /*
            pRTSPThread->StopRTSP();
            usleep(100);

            bPlayerCleanQueue = true;

            nCheckTime.restart();
            while(pRTSPThread->IsWorkingRTSP()==true)
            {
                usleep(100);
                if(nCheckTime.elapsed() > 100)
                {
                    pRTSPThread->StopRTSP();
                    nCheckTime.restart();
                }

            }
            */


        }

        //GStreamer PipeLine is Starting and "Video Link is loss"
        if(pRTSPThread->IsVideoLink()==true)
        {
            if(m_bEncodingVideo==true && bHDMI==true)
            {
                if(pRTSPThread->IsWorkingRTSP()==true && nVideoTime>3*1000)
                {
                    int a=0;
                }
                if(pRTSPThread->GetCaptureMode()==0 && nVideoTime>3*1000)
                {
                    if(ui->pushButton_VID->isEnabled()==true && ui->pushButton_VID->isChecked()==false)
                    {
                        m_nCaptureImageCount++;
                        QString strVideoFilename = pCommonData->GetNewFilename(DISPLAY_VIDEO);
                        pRTSPThread->SetCaptureMode(1);
                        pRTSPThread->SaveFile(strVideoFilename);

                        VideoButtonChange(true);
                        m_TimeCaptureVideo.restart();
                        m_bAutoVideoCapture = false;
                    }
                }
            }
            m_TimerStartPipeLine.restart();
        }
    }

    if(pRTSPThread->IsVideoLink()==true && pRTSPThread->IsWorkingRTSP()==true)
    {
        m_bDisconnectCheck = false;
    }
}

void FormCapture::CheckVideoDevice_old()
{
    QGstreamerPlayer* pPlayer = NULL;
    CommonData* pCommonData = MainWindow::GetCommonData();
    QRTSPThread* pRTSPThread = pCommonData->GetThreadRTSP();

    bool bHDMI = true;
    QElapsedTimer nCheckTime;

    nCheckTime.start();

    //Video Watching Link
    if(m_pThreadWatchVideoLink!=NULL)
    {
        bHDMI = m_pThreadWatchVideoLink->IsConnectHDMI();

        if(bHDMI==false)
        {
            m_bDisconnectCheck = true;
            if(pRTSPThread->IsVideoLink()==true)
            {
                //bHDMI = true;
            }
        }

        if(bHDMI!=m_bPrevConnectHDMI)
        {
            SetHDMICalbeConnect(bHDMI);

            usleep(100*1000);
        }
    }


    if(m_bEncodingVideo==true)
    {
        qint64 nTimeEncodeVideo = m_TimeCaptureVideo.elapsed();
        if(nTimeEncodeVideo < 3 * 1000)
        {
            return;
        }

        //Video Disconnected where Encoding
        if(m_bDisconnectCheck==true)
        {
            //Video Encoding On
            if(pRTSPThread->IsError()==false)
            {
                pRTSPThread->SaveEnd();

                qDebug() << "StopRTSP: Start";
                pRTSPThread->StopRTSP();
                usleep(100*1000);

                ui->widget_Video->Lock();
                {
                    ui->widget_Video->ClearQueueData();
                    ui->widget_Video->SetChangeTexture(true);
                    ui->widget_Video->UpdateTexture();
                }
                ui->widget_Video->Unlock();

                nCheckTime.restart();
                while(pRTSPThread->IsWorkingRTSP()==true)
                {
                    usleep(100);
                    if(nCheckTime.elapsed() > 7*1000)
                    {
                        break;
                    }

                }
                qDebug() << "StopRTSP: Finish";
            }
            else
            {
                //Video Encoding Off
                usleep(1000*10);
            }

            VideoSaveEnd();

            VideoButtonChange(false);
            m_bDisconnectCheck = false;
            m_bEncodingVideo = false;

            ui->widget_Video->Lock();
            {
                ui->widget_Video->ClearQueueData();
                ui->widget_Video->SetChangeTexture(true);
                ui->widget_Video->UpdateTexture();
            }
            ui->widget_Video->Unlock();
        }
    }

    //Save Database when Video Encoding
    if(m_bAutoVideoCapture==false && pRTSPThread->GetCaptureMode()==1)
    {
        if(pRTSPThread->IsWorkingRTSP()==true)
        {
            if(pRTSPThread->IsVideoLink()==true)
            {
                m_bAutoVideoCapture = true;
                m_nCaptureImageCount++;

                QThread::usleep(10*1000);
                m_TimeCapture.restart();

                pCommonData->SetEncodingVideo(true);

                QString strVideoFilename = pCommonData->GetThreadRTSP()->GetVideoFilename();
                CAPTURE_IMAGE* pCaptureImage = NULL;

                {
                    CommonData* pCommonData = MainWindow::GetCommonData();

                    int nWidth = 1920;
                    int nHeight = 1080;

                    QVideoWidget* pVideoWidget = ui->widget_Video;
                    pVideoWidget->Lock();
                    {
                        uint8_t* pData = pVideoWidget->GetCaptureImage();
                        pCaptureImage = pCommonData->AddCaptureImage(pData, nWidth, nHeight, DISPLAY_VIDEO);
                    }
                    pVideoWidget->Unlock();

                    pCaptureImage->m_strVideoFilename = strVideoFilename;

                    bool bCreateImageFile = false;
                    bCreateImageFile = pCommonData->ConvertCaptureImage(pCaptureImage, nWidth, nHeight);

                    pCaptureImage->m_bSaveFile = true;
                    SAFE_DELETE(pCaptureImage->m_pImage);
                    SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
                    SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);
                }

                if(pCaptureImage!=NULL)
                {
                    captureVideo(pCaptureImage);
                }

            }
            else
            {
                int a=0;
            }

        }
        else
        {
            int a=0;
        }

    }

    bool bIsStart = false;
    pPlayer = pRTSPThread->GetGstreamerPlayer();

    if(bIsStart==false)
    {

        if(pPlayer==NULL)
        {
            usleep(1*1000);
        }
        else
        {
            qint64 nTime = m_TimerStartPipeLine.elapsed();

            if(pPlayer->IsPipeStart()==false)
            {
                usleep(1*1000);

                if(pRTSPThread->IsVideoLink()==false)
                {
                    if(nTime>4*1000)
                    {
                        if(pRTSPThread->GetCaptureMode()==1)
                        {
                            pRTSPThread->SaveEnd();

                            QString strVideoFile = pRTSPThread->GetVideoFilename();
                            strVideoFile.replace(".mkv", "_00000.mkv");
                            QFileInfo ff(strVideoFile);
                            if(ff.exists()==true)
                            {
                                qint64 nLength = ff.size();
                                if(nLength>1*1000*1000)
                                {
                                    QString strVideoFilename = pCommonData->GetNewFilename(DISPLAY_VIDEO);
                                    pRTSPThread->SaveFile(strVideoFilename);
                                }
                            }
                            m_bAutoVideoCapture = false;

                            pRTSPThread->ChangeState(6);

                        }
                        else
                        {
                            usleep(1*1000);

                            ui->widget_Video->Lock();
                            {
                                ui->widget_Video->ClearQueueData();
                                ui->widget_Video->SetChangeTexture(true);
                                ui->widget_Video->UpdateTexture();
                            }
                            ui->widget_Video->Unlock();
                            //qDebug() << "StopRTSP";
                            //pRTSPThread->StopRTSP();

                            pRTSPThread->ChangeState(0);
                            qDebug() << "RTSP Thread Start";


                        }

                        usleep(100*1000);

                        m_TimerStartPipeLine.restart();
                    }

                }
                else
                {
                    m_TimerStartPipeLine.restart();
                }
            }
            else
            {
                bIsStart = true;

                if(pRTSPThread->IsVideoLink()==false)
                {
                    if(pRTSPThread->IsStartRTSP()==false && nTime>4*1000)
                    {
                        if(pRTSPThread->GetCaptureMode()==1)
                        {
                            pRTSPThread->SaveEnd();

                            QString strVideoFile = pRTSPThread->GetVideoFilename();
                            strVideoFile.replace(".mkv", "_00000.mkv");
                            QFileInfo ff(strVideoFile);
                            if(ff.exists()==true)
                            {
                                qint64 nLength = ff.size();
                                if(nLength>1*1000*1000)
                                {
                                    QString strVideoFilename = pCommonData->GetNewFilename(DISPLAY_VIDEO);
                                    pRTSPThread->SaveFile(strVideoFilename);
                                }
                            }
                            m_bAutoVideoCapture = false;

                            pRTSPThread->ChangeState(6);
                        }
                        else
                        {
                            pRTSPThread->StopRTSP();
                            usleep(100*1000);

                            ui->widget_Video->Lock();
                            {
                                ui->widget_Video->ClearQueueData();
                                ui->widget_Video->SetChangeTexture(true);
                                ui->widget_Video->UpdateTexture();
                            }
                            ui->widget_Video->Unlock();



                            nCheckTime.restart();
                            while(pRTSPThread->IsWorkingRTSP()==true)
                            {
                                usleep(100);
                                if(nCheckTime.elapsed() > 7*1000)
                                {
                                    int a=0;
                                    break;
                                }

                            }

                            pRTSPThread->ChangeState(0);


                        }

                        usleep(100*1000);

                        m_TimerStartPipeLine.restart();
                    }
                }
                else
                {
                    m_TimerStartPipeLine.restart();
                }



                //m_Timer.stop();
            }
        }

    }

    if(pRTSPThread->IsVideoLink()==true)
    {
        //WRITE_FUNCTION_LOG_PARAM("VideoLink is OK");
        //m_Timer.stop();
    }

}

void FormCapture::on_horizontalSlider_Hue_valueChanged(int value)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(value));
    int nValue = value - 50;

    float fValue = (float)nValue / 50.0f;

    //TestCode

    QGstreamerPlayer* pPlayer = NULL;

    CommonData* pCommonData = MainWindow::GetCommonData();


    bool bIsStart = false;
    if(bIsStart==false)
    {
        pPlayer = pCommonData->GetThreadRTSP()->GetGstreamerPlayer();
        if(pPlayer!=NULL)
        {
            pPlayer->ChangeHue(fValue);
        }
    }
}

void FormCapture::on_horizontalSlider_Saturation_valueChanged(int value)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(value));
    int nValue = value;

    float fValue = (float)nValue / 50.0f;

    //TestCode

    QGstreamerPlayer* pPlayer = NULL;

    CommonData* pCommonData = MainWindow::GetCommonData();


    bool bIsStart = false;
    if(bIsStart==false)
    {
        pPlayer = pCommonData->GetThreadRTSP()->GetGstreamerPlayer();
        if(pPlayer!=NULL)
        {
            pPlayer->ChangeSaturation(fValue);
        }
    }
}

void FormCapture::resizeEvent(QResizeEvent *event)
{
    WRITE_FUNCTION_LOG();
    CommonData* pCommonData = MainWindow::GetCommonData();
    int nDisplayType = pCommonData->GetDisplayType();

    int nFontSize = 22;
    int nFontSizeCaptureTitle = 30;
    int nFontSizeButton = 22;
    int nFontInfoLabel = 22;
    int nFontInfoInfo = 22;
    if(nDisplayType==SDISPLAY_1280X1024)
    {
        nFontSize = 16;
        nFontSizeCaptureTitle = 25;
        nFontSizeButton = 18;
        nFontInfoLabel = 18;
        nFontInfoInfo = 22;
        ui->frame_Viewer_Vertical->hide();
        ui->frame_Viewer_Horizontal->show();
        //ui->frame_capture->setGeometry(40, 45, 1200, 1024-90);
        ui->frame_capture->setGeometry(40, 45, 1200, 934);
        ui->label_Capture->setGeometry(38, 24, 300, 45);
        ui->label_LastCapture->setGeometry(180, 30, 300, 30);
        ui->pushButton_EXIT->setGeometry(1003, 22, 140, 45);
        ui->frame_Line->setGeometry(38, 69, 965+140, 27);
        ui->display_line->setGeometry(0, 27/2, 965+140, 1);
        ui->frame_Info->setGeometry(38, 69+27, 965+140, 59);
        ui->pushButton_ACQ->setGeometry(890-38, 0, 115, 45);
        ui->pushButton_VID->setGeometry(1027-38, 0, 115, 45);
        ui->frame_InfoString->setGeometry(0, 0, 800, 45);
        {
            ui->label_ID->setGeometry(0, 0, 30, 45);
            ui->info_ID->setGeometry(40, 0, 161, 45);
            ui->label_Name->setGeometry(200, 0, 70, 45);
            ui->info_Name->setGeometry(280, 0, 161, 45);
            ui->label_Birth->setGeometry(490, 0, 70, 45);
            ui->info_Birth->setGeometry(570, 0, 161, 45);
        }



        ui->label_StudyDescription->setGeometry(350, 24, 600, 40);
        ui->frame_Detection->setGeometry(780, 24, 180, 40);
        {
            ui->label_Detection->setGeometry(0, 0, 120, 40);
            ui->checkBox_Detection->setGeometry(120, 10, 30, 30);
        }

        ui->widget_Video->setGeometry(39, 155, 1103, 621);
        ui->frame_connect_check->setGeometry(39, 155, 1103, 621);
        {
            //400, 60
            ui->label_connect_check->setGeometry((1103-400)/2, (621-60)/2, 400, 60);
        }
        ui->pushButton_SEND->setGeometry(1026, 155+621+61-45, 115, 45);
        ui->pushButton_DELETE->setGeometry(1026, 155+621+133-45, 115, 45);

        {
            ui->horizontalSlider_Hue->setGeometry(450, 40, 200, 16);
            ui->horizontalSlider_Saturation->setGeometry(680, 40, 200, 16);
        }

        //ui->frame_Viewer_Horizontal->setGeometry(95, 792, 879, 87);
        //ui->horizontalLayoutWidget->setGeometry(0, 0, 879, 87);
        ui->frame_Viewer_Horizontal->setGeometry(39, 792, 1103, 120);
        ui->horizontalLayoutWidget->setGeometry(0, 0, 1103, 120);

        //ui->frame_horizontalScrollBar->setGeometry(97, 911-25, 874, 26);
        //ui->horizontalScrollBar->setGeometry(0, 0, 874, 26);
        ui->frame_horizontalScrollBar->setGeometry(39, 911, 1103, 26);
        ui->horizontalScrollBar->setGeometry(0, 0, 1103, 26);


        ui->frame_SelectBackground->setGeometry(0, 0, 1280, 1024);
        ui->widget_SelectImage->setGeometry(79, 200, 1103, 779);
        ui->frame_SelectBackground->hide();

        //ui->pushButton_EXIT->hide();
        //ui->pushButton_ACQ->hide();
        //ui->pushButton_VID->hide();

        ui->pushButton_SEND->hide();
        ui->pushButton_DELETE->hide();

        //ui->horizontalSlider_Hue->hide();
        //ui->horizontalSlider_Saturation->hide();

        m_nItemPerPage = 5;
    }
    else if(nDisplayType==SDISPLAY_1920X1080)
    {
        nFontSizeCaptureTitle = 30;
        nFontSizeButton = 22;
        nFontInfoLabel = 22;
        nFontInfoInfo = 22;
        ui->frame_Viewer_Vertical->show();
        ui->frame_Viewer_Horizontal->hide();
        ui->frame_capture->setGeometry(36, 36, 1855, 1028);
        ui->label_Capture->setGeometry(55, 30, 200, 40);
        ui->pushButton_EXIT->setGeometry(1580, 27, 161, 51);
        ui->frame_Line->setGeometry(55, 80, 1749, 53);
        ui->display_line->setGeometry(0, 53/2, 1749, 1);
        ui->frame_Info->setGeometry(0, 133, 1855, 96);
        ui->pushButton_ACQ->setGeometry(1399, 0, 153, 63);
        ui->pushButton_VID->setGeometry(1591, 0, 153, 63);
        ui->frame_InfoString->setGeometry(55, 0, 800, 63);
        {
            ui->label_ID->setGeometry(0, 0, 30, 63);
            ui->info_ID->setGeometry(40, 0, 161, 63);
            ui->label_Name->setGeometry(200, 0, 70, 63);
            ui->info_Name->setGeometry(280, 0, 161, 63);
            ui->label_Birth->setGeometry(490, 0, 70, 63);
            ui->info_Birth->setGeometry(570, 0, 161, 63);
        }
        ui->widget_Video->setGeometry(55, 230, 1280, 720);
        ui->pushButton_SEND->setGeometry(1398, 940, 161, 51);
        ui->pushButton_DELETE->setGeometry(1582, 940, 161, 51);

        {
            ui->horizontalSlider_Hue->setGeometry(310, 40, 451, 16);
            ui->horizontalSlider_Saturation->setGeometry(840, 40, 451, 16);
        }

        ui->frame_SelectBackground->setGeometry(0, 0, 1920, 1080);
        ui->widget_SelectImage->setGeometry(55, 230, 1280, 720);

        m_nItemPerPage = 3;
    }

    bool bIsConnectHDMI = pCommonData->IsConnectHDMI();
    SetHDMICalbeConnect(bIsConnectHDMI);

    QString strPushButton_Exit_Delete = QString(
    "QPushButton \
    { \
        background: #FFFFFF; \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: bold; \
        border-radius: 8px; \
        color: black; \
    } \
    QPushButton:pressed \
    { \
        background: #D8D8D8; \
    }").arg(nFontSizeButton);
    ui->pushButton_EXIT->setStyleSheet(strPushButton_Exit_Delete);
    ui->pushButton_DELETE->setStyleSheet(strPushButton_Exit_Delete);


    QString strPushButton_ACQ_IMG = QString(
    "QPushButton \
    { \
        background: #153B44; \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: bold; \
        border-radius: 8px; \
        color: white; \
    } \
    QPushButton:pressed \
    { \
        background: #1B4C54; \
    }").arg(nFontSizeButton);


    QString strPushButton_ACQ_VID = QString(
    "QPushButton "
    "{ "
    "    background: #153B44; "
    "    font-family: 'Roboto'; "
    "    font-size: %1px; "
    "    font-weight: bold; "
    "    border-radius: 8px; "
    "    color: white; "
    "    qproperty-checkable: true; "
    "    qproperty-checked: false; "
    "    qproperty-enabled: true; "
    "} "
    " "
    "QPushButton:pressed "
    "{ "
    "    background: #1B4C54; "
    "} "
    " "
    "QPushButton:checked "
    "{ "
    "    background: red; "
    "} "
    " "
    "QPushButton:disabled "
    "{ "
    "    background: blue; "
    "}").arg(nFontSizeButton);

    ui->pushButton_VID->setStyleSheet(strPushButton_ACQ_VID);

    ui->pushButton_ACQ->setStyleSheet(strPushButton_ACQ_IMG);

    ui->pushButton_SEND->setStyleSheet(strPushButton_ACQ_IMG);


    QString strInfoLabel = QString(
    "QLabel \
    { \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: bold; \
        color: #000000; \
    }").arg(nFontInfoLabel);
    ui->label_ID->setStyleSheet(strInfoLabel);
    ui->label_Name->setStyleSheet(strInfoLabel);
    ui->label_Birth->setStyleSheet(strInfoLabel);

    QString strInfoInfo = QString(
    "QLabel \
    { \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: normal; \
        color: #000000; \
    }").arg(nFontInfoInfo);
    ui->info_ID->setStyleSheet(strInfoInfo);
    ui->info_Name->setStyleSheet(strInfoInfo);
    ui->info_Birth->setStyleSheet(strInfoInfo);


    QString strInfoStudyDescription = QString(
    "QLabel \
    { \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: normal; \
        qproperty-alignment: 'AlignVCenter | AlignHCenter'; \
        color: #000000; \
    }").arg(nFontInfoInfo);
    ui->label_StudyDescription->setStyleSheet(strInfoStudyDescription);


    /*
    if(pCommonData->IsAutoVideoCapture()==true)
    {
        ui->pushButton_VID->setChecked(true);
        ui->pushButton_VID->setDisabled(true);
    }
    else
    {
    */
        ui->pushButton_VID->setChecked(false);
        ui->pushButton_VID->setEnabled(true);
    //}

        #ifdef _PC
            SetHDMICalbeConnect(true);
        #endif

}

void FormCapture::on_pushButton_SEND_clicked()
{
    WRITE_FUNCTION_LOG();

}

void FormCapture::on_pushButton_DELETE_clicked()
{
    WRITE_FUNCTION_LOG();
}

void FormCapture::keyReleaseEvent(QKeyEvent *event)
{
    WRITE_FUNCTION_LOG();
    int nKey = event->key();

    if(nKey==Qt::Key_F10 || nKey==Qt::Key_F11)
    {
        /*
        if(ui->pushButton_ACQ->isEnabled()==true)
        {
            ui->pushButton_ACQ->click();
        }
        */
        m_TimerCaptureSingleShot.start();



    }
    /*
    else if(nKey==Qt::Key_F11)
    {
        if(ui->pushButton_VID->isEnabled()==true)
        {
            ui->pushButton_VID->click();
        }

    }
    */

}

void FormCapture::FinishBeep()
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    pCommonData->Beep(false);
}

void FormCapture::CheckCaptureTimeInfo()
{
    //WRITE_FUNCTION_LOG();
    QString strTimeInfo;

    /*
    CommonData* pCommonData = MainWindow::GetCommonData();
    int nCountCaptureImage = 0;
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
    {
        nCountCaptureImage = pListCaptureImage->size();
    }
    pCommonData->ReleaseListCaptureImage();
    */

    if(m_TimeCapture.isValid()==true && m_nCaptureImageCount>0)
    {
        qint64 nTime = m_TimeCapture.elapsed();
        nTime = nTime/1000;
        int nSecond = nTime%60;
        int nMinute = (nTime/60)%60;
        int nHour = ((nTime/60)/60)%60;
        strTimeInfo = QString("LastCapture: %1:%2:%3").arg(nHour).arg(nMinute).arg(nSecond);
        ui->label_LastCapture->setText(strTimeInfo);
        ui->label_LastCapture->show();
    }
    else
    {
        ui->label_LastCapture->hide();
    }
}


void FormCapture::UpdateObjectDisplay(vector<QRect>& listRectDisplay)
{
    WRITE_FUNCTION_LOG();
    ui->widget_Video->UpdateObjectDisplay(listRectDisplay);
}


void FormCapture::ThumbnailClicked(void* pData)
{
    WRITE_FUNCTION_LOG();
    m_bSendBackground = false;
    ui->frame_SelectBackground->show();
    ui->widget_SelectImage->SetCurrentImage((CAPTURE_IMAGE*)pData);

    ui->widget_Video->hide();

    ui->pushButton_EXIT->hide();
    ui->pushButton_ACQ->hide();
    ui->pushButton_VID->hide();
}


void FormCapture::CloseSelectForm()
{
    WRITE_FUNCTION_LOG();
    ui->frame_SelectBackground->hide();

    ui->widget_Video->show();

    ui->pushButton_EXIT->show();
    ui->pushButton_ACQ->show();
    ui->pushButton_VID->show();

    m_nIndexCurrent = 0;
    UpdateViewer();
    ui->horizontalScrollBar->setValue(0);

    //CommonData* pCommonData = MainWindow::GetCommonData();
    //vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();



    //m_ListFormHorizontalImageSelect.size();
}

void FormCapture::UpdateMakeDICOMInfo(int nCount, int nTotalCount)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(nCount) + "/" + QString::number(nTotalCount));
    if(m_pDialogSendProgress!=NULL)
    {
        m_pDialogSendProgress->DisplayInfo(nCount, nTotalCount);

        QString strInfo = QString("DICOM Make: %1 / %2").arg(nCount).arg(nTotalCount);
        m_pDialogSendProgress->DisplayInfo(strInfo);
    }
    else
    {
        if(m_bSendBackground==false)
        {
            ui->widget_SelectImage->UpdateMakeDICOMInfo(nCount, nTotalCount);
        }

    }

}


void FormCapture::UpdateSendInfo(int nCount, int nTotalCount)
{
    WRITE_FUNCTION_LOG_PARAM(QString::number(nCount) + "/" + QString::number(nTotalCount));
    if(m_pDialogSendProgress!=NULL)
    {
        m_pDialogSendProgress->DisplayInfo(nCount, nTotalCount);

        QString strInfo = QString("%1 / %2").arg(nCount).arg(nTotalCount);
        m_pDialogSendProgress->DisplayInfo(strInfo);
    }
    else
    {
        if(m_bSendBackground==false)
        {
            ui->widget_SelectImage->UpdateSendInfo(nCount, nTotalCount);
        }

    }

}

void FormCapture::UpdateSendComplete()
{
    WRITE_FUNCTION_LOG();
    if(m_pDialogSendProgress!=NULL)
    {
        m_pDialogSendProgress->DisplayInfo(-1, 100);

        //QString strInfo = QString("Send Complete");
        //m_pDialogSendProgress->DisplayInfo(strInfo);

        QThread::msleep(1000);

        //m_pDialogSendProgress->SendComplete();
        //m_pDialogSendProgress->accept();
    }
    else
    {
        if(m_bSendBackground==false)
        {
            ui->widget_SelectImage->UpdateSendComplete();
        }

    }

}

void FormCapture::UpdateSendFailed()
{
    WRITE_FUNCTION_LOG();
    if(m_pDialogSendProgress!=NULL)
    {
        m_pDialogSendProgress->DisplayInfo(-1, 100);

        //QString strInfo = QString("Error: Check Network");
        //m_pDialogSendProgress->DisplayInfo(strInfo);
        m_pDialogSendProgress->DisplayInfo(-1);



        //QThread::msleep(1000);

        //m_pDialogSendProgress->SendComplete();
        //m_pDialogSendProgress->accept();
    }
    else
    {
        if(m_bSendBackground==false)
        {
            ui->widget_SelectImage->UpdateSendFailed();
        }

    }

}

void FormCapture::VideoStopEnable()
{
    WRITE_FUNCTION_LOG();
    ui->pushButton_VID->setEnabled(true);
}


void FormCapture::ImageCaptureEnable()
{
    WRITE_FUNCTION_LOG();
    ui->pushButton_ACQ->setEnabled(true);
}

void FormCapture::CaptureSingleShot()
{
    if(ui->pushButton_ACQ->isEnabled()==false)
    {
        m_TimerCaptureSingleShot.stop();
        return;
    }
    ui->pushButton_ACQ->setDisabled(true);

    CommonData* pCommonData = MainWindow::GetCommonData();
    CAPTURE_IMAGE* pCaptureImage = NULL;
    bool bIsCropMode = (bool)pCommonData->GetCropMode();

    int nWidth = pCommonData->GetVideoWidth();
    int nHeight = pCommonData->GetVideoHeight();
    int nSaveWidth = pCommonData->GetVideoWidth();
    int nSaveHeight = pCommonData->GetVideoHeight();

    m_nCaptureImageCount++;
    m_TimeCapture.restart();

    QVideoWidget* pVideoWidget = ui->widget_Video;
    pVideoWidget->Lock();
    {
        uint8_t* pData = pVideoWidget->GetCaptureImage();

        //SThreadImageSave* pThread = MainWindow::GetCommonData()->GetThreadCaptureImage();
        //pThread->SetImageCapture(pData, 1920, 1080);

        pCaptureImage = pCommonData->AddCaptureImage(pData, nWidth, nHeight, DISPLAY_IMAGE);
    }
    pVideoWidget->Unlock();

    pCommonData->Beep(true);
    m_TimerCaptureBeepSound.start(250);
    m_TimerCaptureImage.start(10);

    bool bCreateImageFile = false;
    bCreateImageFile = pCommonData->ConvertCaptureImage(pCaptureImage, nSaveWidth, nSaveHeight);


    if(bCreateImageFile==false)
    {
        SAFE_DELETE(pCaptureImage->m_pImage);
        SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
        SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);

        vector<CAPTURE_IMAGE*>::iterator it;
        vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();
        {
            for(it=pListCaptureImage->begin() ; it!=pListCaptureImage->end() ; ++it)
            {
                CAPTURE_IMAGE* pImageDisplay = *it;
                if(pImageDisplay==pCaptureImage)
                {
                    pListCaptureImage->erase(it);
                    break;
                }
            }
        }
        pCommonData->ReleaseListCaptureImage();

        SAFE_DELETE(pCaptureImage);

        m_TimerCaptureSingleShot.stop();
        return;
    }

    m_nCaptureImageCount++;
    m_TimeCapture.restart();


    /*
    if(bIsCropMode==true)
    {
        *pCaptureImage->m_pImage = pCaptureImage->m_pImage->copy(QRect(242, 5, 1376, 992));
        //SAFE_DELETE(pCaptureImage->m_pImageSmall);
        //pCaptureImage->m_pImageSmall = new QImage;
        *pCaptureImage->m_pImageSmall = pCaptureImage->m_pImage->scaled(pCaptureImage->m_pImage->width()/4, pCaptureImage->m_pImage->height()/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).copy();

    }
    */
    SAFE_DELETE(pCaptureImage->m_pImage);
    SAFE_DELETE(pCaptureImage->m_pImageCaptureRaw);
    SAFE_ARRAY_DELETE(pCaptureImage->m_pImageCaptureColor);


    if(pCaptureImage!=NULL)
    {
        captureImage(pCaptureImage);
    }

    m_TimerCaptureSingleShot.stop();


    /*
    if(m_TimeHandSwitchOn.elapsed()<1100)
    {
        return;
    }
    CommonData* pCommonData = MainWindow::GetCommonData();
    int nValue = pCommonData->GetHandSwitchValue();

    //qDebug() << nValue;

    if(nValue>=0)
    {
        m_nHandSwitchValue = nValue;

        if(m_nHandSwitchValue==1 && m_nPrevHandSwitchValue==0)
        {
            if(ui->pushButton_ACQ->isEnabled()==true)
            {
                WRITE_FUNCTION_LOG_PARAM("HandSwitch-Clicked!!");
                ui->pushButton_ACQ->click();
                m_TimeHandSwitchOn.start();

            }
        }

        m_nPrevHandSwitchValue = nValue;
    }
    */

}

void FormCapture::CaptureHandSwitch()
{
    WRITE_FUNCTION_LOG();
    if(this->isVisible()==false)
    {
        return;
    }

    m_TimerCaptureSingleShot.start();

    /*
    if(ui->pushButton_ACQ->isEnabled()==true)
    {
        ui->pushButton_ACQ->click();
        //m_TimeHandSwitchOn.start();
    }
    */
}

void FormCapture::CaptureFootSwitch()
{
    WRITE_FUNCTION_LOG();
    if(this->isVisible()==false)
    {
        return;
    }

    m_TimerCaptureSingleShot.start();

    /*
    if(ui->pushButton_ACQ->isEnabled()==true)
    {
        ui->pushButton_ACQ->click();
        //m_TimeHandSwitchOn.start();
    }
    */
}

void FormCapture::on_checkBox_Detection_toggled(bool checked)
{
    WRITE_FUNCTION_LOG();
    CommonData* pCommonData = MainWindow::GetCommonData();
    pCommonData->SetActiveDetect(checked);
}

void FormCapture::OnDoubleClicked()
{
    WRITE_FUNCTION_LOG();

}


void FormCapture::SetHDMICalbeConnect(bool bCableConnect)
{
    int nFontSizeCaptureTitle = 25;
    QString strCaptureTitle = QString(
    "QLabel \
    { \
        font-family: 'Roboto'; \
        font-size: %1px; \
        font-weight: bold; \
        color: #000000;	\
    }").arg(nFontSizeCaptureTitle);

    if(bCableConnect==false)
    {
        strCaptureTitle = QString(
                    "QLabel \
                    { \
                        font-family: 'Roboto'; \
                        font-size: %1px; \
                        font-weight: bold; \
                        color: #FF0000;	\
                    }").arg(nFontSizeCaptureTitle);
                    ui->frame_connect_check->show();

                    ui->widget_Video->ClearQueueData();

                    //ui->pushButton_CON->setEnabled(true);


    }
    else
    {
                    ui->frame_connect_check->hide();

                    //ui->pushButton_CON->setEnabled(false);
                    //ui->pushButton_CON->setEnabled(true);

    }


    ui->label_Capture->setStyleSheet(strCaptureTitle);
}

void FormCapture::HDMICalbeConnect(bool bCableConnect)
{
    if(isVisible()==false)
    {
        return;
    }

    if(isEnabled()==false)
    {
        return;
    }

    SetHDMICalbeConnect(bCableConnect);


}


void FormCapture::WriteDatabaseListCapture()
{
    CommonData* pCommonData = MainWindow::GetCommonData();

    // 1. 다른 공유 데이터에 대한 Lock/Unlock 로직은 그대로 유지합니다.
    ACQUISITION_INFO* pAcquisitionInfo = pCommonData->GetAcquisitionInfo();
    vector<CAPTURE_IMAGE*>* pListCaptureImage = pCommonData->GetListCaptureImage();

    // 포인터가 유효한지 확인하는 방어 코드 추가
    if (!pAcquisitionInfo || !pListCaptureImage) {
        qWarning() << "WriteDatabaseListCapture: Failed to get acquisition info or capture list.";
        if (pAcquisitionInfo) pCommonData->ReleaseAcquisitionInfo();
        if (pListCaptureImage) pCommonData->ReleaseListCaptureImage();
        return;
    }

    // 2. 이 함수만을 위한 지역 DB 인스턴스를 생성하고 연결합니다.
    SUTIL::SDatabase db(QString("WriteCaptureList_%1").arg(reinterpret_cast<quintptr>(this)));
    if (db.OpenDatabase("/home/birdhead/test.db") == 0) // 0이 성공
    {
        // 3. 지역 인스턴스 'db'를 사용하여 DB 작업을 수행합니다.
        //    UpdateImageOnAcquistionTemp 함수는 vector를 포인터(*)가 아닌 참조(&)로 받으므로,
        //    *pListCaptureImage 와 같이 역참조하여 전달합니다.
        db.UpdateImageOnAcquistionTemp(pAcquisitionInfo, *pListCaptureImage);
    }
    else
    {
        qWarning() << "DB open failed in WriteDatabaseListCapture.";
    }

    // 4. GetDatabase/ReleaseDatabase 호출은 완전히 제거됩니다.

    pCommonData->ReleaseAcquisitionInfo();
    pCommonData->ReleaseListCaptureImage();

    // 'db' 객체는 이 함수의 스코프가 끝나면 자동으로 소멸되어 자원이 정리됩니다.
}
