#include "fm_daytime.h" #if (USE_DATE_TIME_LIST) #include #include #include #include #include #include #include #include "../rm_include.h" #include "../data/rm_video_list.h" #include "../data/rm_video_item_2ch.h" #include "../core/rm_math.h" #include "fm_colors.h" #include "../data/an6000_decode.h" #include "../core/rm_player.h" FMTimeBarMinute::FMTimeBarMinute(QWidget *parent) : FMTimeBar(0,60,1,5,parent) { } void FMTimeBarMinute::reset() { FMTimeBar::reset(); mFiles.clear(); mAreas.clear(); mStartBackup = -1; mEndBackup = -1; backups.clear(); } int FMTimeBarMinute::findAreaFromTime(QDateTime* time) { for(int i=0;istartTime() == *time) { return i; } } return -1; } int FMTimeBarMinute::getTime(QPoint xy) { for(int i=0;ititle() << mFiles.at(i).second->durationInMSecs() / 1000 << __FUNCTION__; QSize s = mFiles.at(i).first; int sx = (int)((((double)s.width()) / 3600.0) * aw); sx = qMax(lastX,sx); // 이전 영역과 겹치지 않도록.. int ex = (int)((((double)s.height()) / 3600.0) * aw); // 영역 초과하지 않도록 수정 ex = qMax(qMin(ex,w-(mMarginLR*2)),sx+5); lastX = ex; //qInfo() << ex << w-mMarginLR << __FUNCTION__; QRect r = QRect(mMarginLR+sx,yo,ex-sx,barHeight); //r.adjust(1,1,-1,-1); mAreas.append(QPair(r,mFiles.at(i).second)); } mFiles.clear(); // 필요없으니 제거 } void FMTimeBarMinute::mousePressEvent(QMouseEvent* event) { Q_UNUSED(event) if(mHoverTime >= 0) { if(event->button() == Qt::LeftButton) { mPressed = true; mMenu = false; update(); } else if (event->button() == Qt::RightButton) { mMenu = true; mPressed = false; } } } void FMTimeBarMinute::showMenu(QPoint pos) { QMenu contextMenu("", this); QAction* aStart = new QAction(FM_WSTR(L"バックアップ開始時間"), this); QPairds = QPair(true,mHoverTime); aStart->setData(QVariant::fromValue(ds)); connect(aStart, SIGNAL(triggered()), this, SLOT(onSetBackup())); contextMenu.addAction(aStart); if(mStartBackup > -1) { aStart->setEnabled(false); } QAction* aEnd = new QAction(FM_WSTR(L"バックアップ終了時間"), this); QPairde = QPair(false,mHoverTime); aEnd->setData(QVariant::fromValue(de)); connect(aEnd, SIGNAL(triggered()), this, SLOT(onSetBackup())); contextMenu.addAction(aEnd); if(mEndBackup > -1) { aEnd->setEnabled(false); } if(mStartBackup > -1 || mEndBackup > -1) { // リセット)の方法を教えてください。 QAction* aCancel = new QAction(FM_WSTR(L"リセット"), this); //QPairde = QPair(false,mHoverTime); //aCancel->setData(QVariant::fromValue(de)); connect(aCancel, SIGNAL(triggered()), this, SLOT(onSetBackup())); contextMenu.addAction(aCancel); } contextMenu.exec(mapToGlobal(pos)); } void FMTimeBarMinute::onSetBackup() { QAction* a = qobject_cast(sender()); if(a != NULL) { QString typeName = QString(a->data().typeName()); if( typeName == "QPair") { QPair param = a->data().value>(); if (param.first) { // start mStartBackup = param.second; } else { // end mEndBackup = param.second; } // 추가 if(mStartBackup > -1 && mStartBackup < mAreas.size() && mEndBackup > -1 && mEndBackup < mAreas.size()) { backups.clear(); for(int i=mStartBackup;i<=mEndBackup;i++) { backups.append(mAreas.at(i).second); } emit backupSelected(backups); } update(); } else { mStartBackup = -1; mEndBackup = -1; update(); } } } void FMTimeBarMinute::mouseReleaseEvent(QMouseEvent* event) { Q_UNUSED(event) if(mMenu && event->button() == Qt::RightButton) { mPressed = false; if(mHoverTime >= 0) { showMenu(event->pos()); } return; } FMTimeBar::mouseReleaseEvent(event); } void FMTimeBarMinute::paintEvent(QPaintEvent * pe) { Q_UNUSED(pe) static QPixmap dc = QPixmap(":/image/down_check.png"); QPainter painter(this); drawGrid(painter); for(int i=0;i 30 ? -1 : 0); painter.setPen(QPen(QColor(0x88,0x88,0x88),1, Qt::SolidLine)); painter.drawRect(out); } FMTimeBar::FMTimeBar(int min, int max, int unit, int labelUnit, QWidget *parent) : mMin(min), mMax(max), mUnit(unit),mLabelUnit(labelUnit), QWidget(parent) { bDisabled = false; mMarginLR = 12; mPressed = false; mHoverTime = -1; mSelectedTime = -1; // 이벤트 등록해야 포커스 아닌 상태에서도 동작 가능 QCoreApplication::instance()->installEventFilter(this); } void FMTimeBar::reset() { mPressed = false; mHoverTime = -1; mSelectedTime = -1; mExists.clear(); } void FMTimeBar::showEvent(QShowEvent* e) { // margin 최적화 int cw = (size().width() - (mMarginLR * 2)) / mMax; mMarginLR = (size().width() - cw * mMax) / 2; QWidget::showEvent(e); } bool FMTimeBar::eventFilter(QObject *watched, QEvent *event) { if (watched == this && event->type() == QEvent::MouseMove && !mPressed) { QMouseEvent* me = static_cast(event); // 날짜가 변경된 경우에만 업데이트 int d = getTime(me->pos()); if(d != mHoverTime) { mHoverTime = d; update(); } return false; } return QWidget::eventFilter(watched, event); } int FMTimeBar::getTime(QPoint xy) { QRect r = rect(); if(xy.x() < mMarginLR || xy.x() > r.size().width() - mMarginLR) { return -1; } const int barHeight = size().height() / 2; const int barWidth = (size().width() - (mMarginLR * 2)) / mMax; const int yo = (r.size().height() - barHeight) / 2; if (xy.y() < yo || xy.y() > size().height() - yo) { return -1; } return (xy.x() - mMarginLR) / barWidth; } void FMTimeBar::drawGrid(QPainter& p) { const int offset_x = mMarginLR; const int w = (size().width() - (offset_x * 2)) / mMax; const int h = size().height(); const int barHeight = h / 2; const int y1 = (h - barHeight) / 2 - 4; // -4 = ymargin p.setPen(QPen(QColor(0x66,0x66,0x66),1, Qt::SolidLine)); // 눈금만 그리기 for(int c=0;c 30 ? -1 : 0); painter.setPen(QPen(QColor(0x88,0x88,0x88),1, Qt::SolidLine)); painter.drawRect(out); } void FMTimeBar::mousePressEvent(QMouseEvent* event) { Q_UNUSED(event) if(mExists.contains(mHoverTime) && event->button() == Qt::LeftButton) { mPressed = true; update(); } } void FMTimeBar::mouseReleaseEvent(QMouseEvent* event) { Q_UNUSED(event) if(mPressed && event->button() == Qt::LeftButton) { mPressed = false; if(mHoverTime >= 0) { mSelectedTime = mHoverTime; // 선택상태 emit timeSelected(mSelectedTime,NULL,true); } update(); } } FMDayTime::FMDayTime(QWidget *parent) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(this); ZERO_LAYOUT(layout); mHours = new FMTimeBar(0,24,1,3,this); mHours->setFixedHeight(55); layout->addWidget(mHours); mMinutes = new FMTimeBarMinute(this); mMinutes->setFixedHeight(55); layout->addWidget(mMinutes); setFixedHeight(110); connect(mHours,SIGNAL(timeSelected(int,QDateTime*,bool)),this,SLOT(onHourSelected(int,QDateTime*,bool))); connect(mMinutes,SIGNAL(timeSelected(int,QDateTime*,bool)),this,SLOT(onMinuteSelected(int,QDateTime*,bool))); connect(mMinutes,SIGNAL(backupSelected(QList&)),this,SLOT(onBackupSelected(QList&))); connect(RMPlayer::instance(),SIGNAL(playEvent(PLAY_EVENT,RMVideoItem*)),SLOT(onPlayEvent(PLAY_EVENT,RMVideoItem*))); } void FMDayTime::getHour(QSet& hours) { hours.clear(); for(int i=0;istartTime().time().hour()); } } void FMDayTime::loadMinutes(QList>& files) { files.clear(); // 2024/09/24 ...(1) 파일등을 처리하기 위해 동일한 '초' 의 가장 최초 파일만 추가 QTime lastTime; for(int i=0;istartTime().time(); t = QTime(t.hour(),t.minute(),t.second()); // msec 제거하고 비교하여 제거 if(lastTime.isValid() && t == lastTime) { continue; } lastTime = t; if(t.hour() == mHours->mSelectedTime) { int s = t.minute() * 60 + t.second(); int e = s + mDayList.at(i)->durationInMSecs() / 1000; files.append(QPair(QSize(s,e),item)); } } mMinutes->createAreaBox(); } //void FMDayTime::onPlayEvent(PLAY_EVENT event,RMVideoItem* item) //{ // if(event == PLAY_WILL_LOADED && item != NULL) // { // QDate pdate = item->startTime().date(); // // 리스트 또는 다음파일 이동에서 재생되었는지 // // '분' 항목에서 재생되었는지 확인 필요 // QDate cdate = QDate(mCalendar->date.year(),mCalendar->date.month(),mCalendar->mSelectedDay); // if(cdate != pdate) { // mCalendar->date.setDate(pdate.year(),pdate.month(),pdate.day()); // mCalendar->mSelectedDay = pdate.day(); // mCalendar->update(); // 다시 그리기 // // 년/월이 변경되었을 경우 달력을 다시 로딩 // if(mCalendar->date.year() != pdate.year() || mCalendar->date.month() != pdate.month()) // { // onChangeMonth(); // 달력 업데이트 // } // mCalendar->updateDayItems(); // 날짜리스트 다시 로딩 // emit mCalendar->dateSelected(&mCalendar->mDayItems,false); // //qInfo() << "DATE CHANGED:" << mCalendar->date << pdate << __FUNCTION__; // } // } //} void FMDayTime::onPlayTime(QDateTime* playTime, bool moveList) { // 날짜는 변경되지 않고 시간만 변경되었을 경우 발생 if(playTime != NULL && *playTime == mLastPlayTime) { //qInfo() << "LOOP SKIP!!!" << __FUNCTION__; return; } selectHour(playTime->time().hour(),playTime,moveList); mHours->update(); // 화면갱신해야함 } void FMDayTime::onClearDate() { mDayList.clear(); mMinutes->reset(); // 일단 초기화 mHours->reset(); // " mHours->update(); mMinutes->update(); } void FMDayTime::onDateSelected(QList* dayItems,QDateTime* playTime, bool moveList) { // 현재시간과 동일할 경우 SKIP if(playTime != NULL && *playTime == mLastPlayTime) { return; } // 복사, 보관 mDayList.clear(); mDayList = *dayItems; mDayList.detach(); mMinutes->reset(); // 일단 초기화 mHours->reset(); // " // 시간 확인 getHour(mHours->mExists); // 최초 시간 선택 -> 분데이터 로딩, 캘린더 UI 선택시에만 최초시간 선택 // playTime 이 존재할 경우 최초 시간 무시 if(!mDayList.isEmpty()) { // 루프방지 확인을 위한 날짜를 지정 selectHour(mDayList.first()->startTime().time().hour(),playTime,moveList); } mHours->update(); //mMinutes->update(); } void FMDayTime::selectHour(int hour,QDateTime* playTime,bool moveList) { if(mHours->mExists.contains(hour)){ if(playTime == NULL) { mHours->mSelectedTime = hour; } else { mHours->mSelectedTime = playTime->time().hour(); } onHourSelected(mHours->mSelectedTime,playTime,moveList); } } void FMDayTime::onHourSelected(int hour,QDateTime* playTime,bool moveList) { Q_UNUSED(hour) // 선택된 분 처리하고 mMinutes->reset(); loadMinutes(mMinutes->mFiles); if(playTime!= NULL) { // 분 AREA 확인 mMinutes->mSelectedTime = mMinutes->findAreaFromTime(playTime); } // 리스트 업데이트 해야함 // 달력에서 선택된 경우에만 최초 시간으로 업데이트 + 리스트로 이벤트 전송 // 시간등이 선택되었을 경우 해당 분의 파일로 이동 if(moveList){ // playTime == NULL) { RMVideoItem* first = findFirstSelectedHourItem(); if(first != NULL) { emit listMove(first); } } mMinutes->update(); } RMVideoItem* FMDayTime::findFirstSelectedHourItem() { for(int i=0;istartTime().time(); // 선택된 시간만 확인 if(t.hour() == mHours->mSelectedTime) { return mDayList.at(i); } } return NULL; } RMVideoItem* FMDayTime::findSelectedItem() { return mMinutes->mAreas.at(mMinutes->mSelectedTime).second; // for(int i=0;istartTime().time(); // // 선택된 시간만 확인 // if(t.hour() == mHours->mSelectedTime && t.minute() == mMinutes->mSelectedTime) { // return mDayList.at(i); // } // } // return NULL; } void FMDayTime::onEnable() { //qInfo() << mMinutes->bDisabled << __FUNCTION__; mMinutes->bDisabled = false; this->setEnabled(true); QApplication::restoreOverrideCursor(); } void FMDayTime::onPlayEvent(PLAY_EVENT event,RMVideoItem* item) { Q_UNUSED(item) if(event == PLAY_DID_LOADED) { QTimer::singleShot(200,Qt::PreciseTimer,this,SLOT(onEnable())); } } void FMDayTime::onMinuteSelected(int minute, QDateTime* playTime,bool moveList) { Q_UNUSED(moveList) // mMinutes->mSelectedTime Q_UNUSED(minute) if(playTime == NULL) { RMVideoItem* selected = findSelectedItem(); if(selected != NULL) { // 스스로 재생한 시간을 기록하여 LOOP 방지 mLastPlayTime = selected->startTime(); QApplication::setOverrideCursor(Qt::WaitCursor); // qInfo() << mMinutes->bDisabled << __FUNCTION__; mMinutes->bDisabled = true; //mMinutes->update(); setEnabled(false); //QTimer::singleShot(500,Qt::PreciseTimer,this,SLOT(onEnable())); int old = RMVideoFileList::instance()->getPlayIndex(); emit RMVideoFileList::instance()->playItemFound(selected,old); } } //qInfo() << selected->filePath << __FUNCTION__; } void FMDayTime::onBackupSelected(QList& lst) { QString start = lst.first()->startTime().toString("HH:mm:ss"); QString end = lst.last()->startTime().toString("HH:mm:ss"); QMessageBox msgBox(QMessageBox::NoIcon, FM_WSTR(L"ファイルのコピー"), FM_WSTR(L"ファイルのコピーを開始します。\nコピー範囲 :") + start + QString(" ~ ") + end, QMessageBox::Yes | QMessageBox::No, this); msgBox.setStyleSheet("QLabel{min-width: 260px;}"); msgBox.setWindowFlags(Qt::WindowTitleHint | Qt::Dialog | Qt::CustomizeWindowHint); msgBox.setButtonText(QMessageBox::Yes, "OK"); msgBox.setButtonText(QMessageBox::No, FM_WSTR(L"キャンセル")); if (QMessageBox::Yes == msgBox.exec()) { QString folder = RMApp::openFolder(RMSettings::instance()->lastBackupPath(),false,FM_WSTR(L"ファイルのコピーのパスを選択")); if(QDir(folder).exists()) { RMSettings::instance()->setLastBackupPath(folder); QString copyFolder = "Copy_" + lst.first()->startTime().toString("yyyyMMdd_HHmmss"); folder = QDir::cleanPath(folder + QDir::separator() + copyFolder); // 폴더 생성 if(!QDir(folder).exists()) { QDir().mkdir(folder); } QApplication::setOverrideCursor(Qt::WaitCursor); for(int i=0;ifilePath); QString dest = QDir::cleanPath(folder + QDir::separator() + fi.fileName()); if(QFile(dest).exists()) { QFile(dest).remove(); } QFile::copy(lst.at(i)->filePath, dest); if(is_encrypted_an6000(dest.toStdWString().c_str())) { decrypt_an6000(dest.toStdWString().c_str()); } } QApplication::restoreOverrideCursor(); QMessageBox::information(this,FM_WSTR(L"ファイルのコピー"),FM_WSTR(L"完了しました。"),"OK"); } } } #endif // #if (USE_DATE_TIME_LIST)