#include "fm_calendar.h" #if (USE_DATE_TIME_LIST) #include #include #include #include #include #include #include "rm_include.h" #include "../ui/fm_button.h" #include "../data/rm_video_list.h" #include "../data/rm_video_item_2ch.h" #include "fm_colors.h" #include "../core/rm_player.h" FMCalendarFrame::FMCalendarFrame(QWidget *parent) : QWidget(parent) { bLoadStarted = true; setFixedHeight(250); mLayout = new QVBoxLayout(this); ZERO_LAYOUT(mLayout); QWidget* toolbar = new QWidget(this); toolbar->setFixedHeight(30); mLayout->addWidget(toolbar); QHBoxLayout* toolLayout = new QHBoxLayout(toolbar); ZERO_LAYOUT(toolLayout); before = FMButton::btnTypeTextColor(toolbar,toolLayout," < ","",QSize(20,20),g_default_text_button_color_set); connect(before,SIGNAL(clicked()),SLOT(onChangeMonth())); mYearLabel = new QLabel(toolbar); mYearLabel->setAlignment(Qt::AlignCenter); mYearLabel->setStyleSheet("font-family: Fixedsys;color : #DDDDDD;"); toolLayout->addWidget(mYearLabel); next = FMButton::btnTypeTextColor(toolbar,toolLayout," > ","",QSize(20,20),g_default_text_button_color_set); connect(next,SIGNAL(clicked()),SLOT(onChangeMonth())); mCalendar = new FMCalendar(this); mLayout->addWidget(mCalendar); RMVideoFileList* fileList = RMVideoFileList::instance(); //connect(fileList,SIGNAL(listUpdateEnd(bool,RMVideoItem*)),this,SLOT(onListUpdateEnd(bool,RMVideoItem*))); connect(fileList,SIGNAL(listUpdateStarted(bool)),this,SLOT(onListUpdateStarted(bool))); refreshMonth(); //connect(fileList,SIGNAL(playItemFound(RMVideoItem*,int)),SLOT(onPlayItemFound(RMVideoItem*,int))); //connect(fileList,SIGNAL(playNoMoreItem()),SLOT(onPlayNoMoreItem())); connect(RMPlayer::instance(),SIGNAL(playEvent(PLAY_EVENT,RMVideoItem*)),SLOT(onPlayEvent(PLAY_EVENT,RMVideoItem*))); } void FMCalendarFrame::onPlayEvent(PLAY_EVENT event,RMVideoItem* item) { // PLAY_WILL_LOADED if(event == PLAY_ITEM_SELECTED && item != NULL) { playTime = item->startTime(); QDate pdate = item->startTime().date(); // 리스트 또는 다음파일 이동에서 재생되었는지 // '분' 항목에서 재생되었는지 확인 필요 QDate cdate = QDate(mCalendar->date.year(),mCalendar->date.month(),mCalendar->mSelectedDay); if(cdate != pdate || bLoadStarted) { // 년/월이 변경되었을 경우 달력을 다시 로딩 // 2023/06/30 -> 2023/07/01 로 변경시 적용안됨? if(bLoadStarted || mCalendar->date.year() != pdate.year() || mCalendar->date.month() != pdate.month()) { mCalendar->date.setDate(pdate.year(),pdate.month(),pdate.day()); mCalendar->mSelectedDay = pdate.day(); onChangeMonth(); // 달력 업데이트 } mCalendar->date.setDate(pdate.year(),pdate.month(),pdate.day()); mCalendar->mSelectedDay = pdate.day(); mCalendar->update(); // 다시 그리기 mCalendar->updateDayItems(); // 날짜리스트 다시 로딩 // 리스트에서 전달되었으므로 리스트 없데이트 X emit mCalendar->dateSelected(&mCalendar->mDayItems,&playTime,false); //qInfo() << "DATE CHANGED:" << mCalendar->date << pdate << __FUNCTION__; } else { // 시간만 변경된 경우 //qInfo() << playTime << __FUNCTION__; // 리스트에서 전달되었으므로 리스트 없데이트 X emit mCalendar->playTime(&playTime,false); } if(bLoadStarted) { bLoadStarted = false; } } else if (event == PLAY_DID_CLEARED) { /* mCalendar->mSelectedDay = -1; mCalendar->update(); */ } } void FMCalendarFrame::onListUpdateStarted(bool bLoading) { // 2회 발생하는 경우도 있으며 bLoading false 로 .. if(bLoading) { bLoadStarted = true; } //qInfo() << bLoadStarted << __FUNCTION__; } /* // 파일 선택되면서 자동으로 처리되어 필요없음 ... -> // 현재 표시되는 '월'일 경우 파일이 선택되더라도 자동으로 업데이트가 안되니 // 강제 업데이트가 필요함 onPlayEvent 의 PLAY_ITEM_SELECTED 는 // onListUpdateEnd 이전에 발생함 void FMCalendarFrame::onListUpdateEnd(bool bLoading, RMVideoItem* selected) { Q_UNUSED(bLoading) Q_UNUSED(selected) if(bLoading) { qInfo() << selected << __FUNCTION__; } } */ void FMCalendarFrame::onChangeMonth() { FMButton* btn = qobject_cast(sender()); if(btn == next) { mCalendar->date = mCalendar->date.addMonths(1); } else if (btn == before) { mCalendar->date = mCalendar->date.addMonths(-1); } RMVideoFileList::instance()->getMonthList(mCalendar->date.year(),mCalendar->date.month(),mCalendar->mExists,mCalendar->mMonthItems); // 월의 첫날짜로 구분 if(mCalendar->mMonthItems.isEmpty()) { // 없을경우... mCalendar->mSelectedDay = -1; } else { mCalendar->mSelectedDay = mCalendar->mMonthItems.first()->startTime().date().day(); } // 월 텍스트 변경 refreshMonth(); // 재생시 리스트 변경의 경우 if(btn == NULL) { return; } mCalendar->updateDayItems(); mCalendar->update(); // 선택된 달에 영상이 존재할 경우 if(!mCalendar->mMonthItems.isEmpty()) { static QDateTime tt; tt = mCalendar->mDayItems.first()->startTime(); // 달력업데이트로 처리 하였으니 리스트 업데이트 = true emit mCalendar->dateSelected(&mCalendar->mDayItems,&tt,true); } else { emit mCalendar->clearDate(); // 해당월에 날짜 없음 } } void FMCalendarFrame::refreshMonth() { mYearLabel->setText(QString::number(mCalendar->date.year()) + FM_WSTR(L"年 / ") + QString::number(mCalendar->date.month()) + FM_WSTR(L"月")); } FMCalendar::FMCalendar(QWidget *parent) : QWidget(parent) { date = QDateTime::currentDateTime().date();// .setDate(2023,11,1); mPressed = false; mHoverDay = -1; mSelectedDay = -1; // 이벤트 등록해야 포커스 아닌 상태에서도 동작 가능 QCoreApplication::instance()->installEventFilter(this); } /* void FMCalendar::selectDay(int day) { if(mExists.contains(day)) { mSelectedDay = day; updateDayItems(); qInfo() << __FUNCTION__; emit dateSelected(&mDayItems,NULL); } } */ void FMCalendar::reset() { mPressed = false; mHoverDay = -1; mSelectedDay = -1; mMonthItems.clear(); mDayItems.clear(); mExists.clear(); } int FMCalendar::getDay(QPoint xy) { QDate d = QDate(date.year(),date.month(),1); // 월별 일수 int days = d.daysInMonth(); // 요일 일=0,월=1, 화=2, 수=3 int dayOfWeek = d.dayOfWeek() % 7; const int colCount = 7; int rowCount = ceil(((double)(days + dayOfWeek) / (double)colCount)) + 1; // week of days //int rowCount = ceil(((double)(days + dw) / (double)colCount)) + 1; // week of days //QRect r = rect(); const int cw = size().width() / colCount; const int rh = size().height() / rowCount; int currentDay = 1; for(int r=1;r days) { //qInfo() << "c < dayOfWeek:" << (c < dayOfWeek) << "c:" << c << "dayOfWeek:" << dayOfWeek << __FUNCTION__; continue; } // int left, int top, int width, int height QRect cr = QRect(c*cw,r*rh,cw,rh); if(cr.contains(xy)) { return currentDay; } currentDay++; } } return -1; } bool FMCalendar::eventFilter(QObject *watched, QEvent *event) { if (watched == this && event->type() == QEvent::MouseMove && !mPressed) { QMouseEvent* me = static_cast(event); // 날짜가 변경된 경우에만 업데이트 int d = getDay(me->pos()); if(d != mHoverDay) { mHoverDay = d; update(); } return false; } return QWidget::eventFilter(watched, event); } void FMCalendar::mousePressEvent(QMouseEvent* event) { Q_UNUSED(event) if(mExists.contains(mHoverDay) && event->button() == Qt::LeftButton) { mPressed = true; update(); } } void FMCalendar::updateDayItems() { mDayItems.clear(); for(int i=0;istartTime().date(); if(d.day() == mSelectedDay) { mDayItems.append(mMonthItems.at(i)); } } } void FMCalendar::mouseReleaseEvent(QMouseEvent* event) { Q_UNUSED(event) if(mPressed && event->button() == Qt::LeftButton) { mPressed = false; if(mHoverDay > 0) { mSelectedDay = mHoverDay; updateDayItems(); static QDateTime tt = mDayItems.first()->startTime(); // 달력에서 업데이트 되었으니 리스트 업데이트 emit dateSelected(&mDayItems,&tt,true); // 선택된 날짜의 파일로 이동 // X // if(!mDayItems.isEmpty()) { // emit listMove(mDayItems.first()); // } } update(); } } void FMCalendar::paintEvent(QPaintEvent *e) { QWidget::paintEvent(e); //QDate d = QDate(mYear,mMonth,1); // 월별 일수 (지정된 날짜의 1일로 확인) QDate d = QDate(date.year(),date.month(),1); int days = d.daysInMonth(); // 요일 일=0,월=1, 화=2, 수=3, 일=7?? int dw = d.dayOfWeek() % 7; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, false); const int colCount = 7; // 1일의 시작요일을 더해서 ROW 계산 필요 int rowCount = ceil(((double)(days + dw) / (double)colCount)) + 1; // week of days //qInfo() << days << colCount << "rowCount" << rowCount << __FUNCTION__; QRect r = this->rect(); r.adjust(0,0,-1,-1); painter.fillRect(r,QColor(0x33,0x33,0x33)); int cw = size().width() / colCount; int rh = size().height() / rowCount; QString wd = FM_WSTR(L"日月火水木金土"); // 일~토 레이블 출력 painter.setPen(QPen(QColor(0xFF,0xFF,0xFF),1, Qt::SolidLine)); for(int c=0;c days) { //qInfo() << "SKIP r:" << r << "rowCount:" << rowCount << "dw:" << dw << "c:" << c << __FUNCTION__; continue; } // int left, int top, int width, int height QRect cr = QRect(c*cw,r*rh,cw,rh); cr.adjust(1,1,-1,-1); // 영상이 존재하는 날자일 경우 if(mExists.contains(currentDay)) { painter.fillRect(cr,QColor(FM_SILDER_COLOR)); if (currentDay == mSelectedDay) { QRect cc = cr; cc.adjust(4,4,-4,-4); QPen p = QPen(QColor(FM_SELECTED_COLOR),5, Qt::SolidLine); p.setJoinStyle(Qt::MiterJoin); painter.setPen(p); painter.drawRect(cc); } else if(currentDay == mHoverDay) { QRect cc = cr; cc.adjust(4,4,-4,-4); QPen p = QPen(QColor(FM_HOVER_COLOR),5, Qt::SolidLine); p.setJoinStyle(Qt::MiterJoin); painter.setPen(p); painter.drawRect(cc); } } painter.setPen(QPen(QColor(0x44,0x44,0x44),1, Qt::SolidLine)); // setJoinStyle(Qt::MiterJoin); painter.drawRect(cr); // 일요일은 붉은색 painter.setPen(QPen(c == 0 ? QColor(0xDD,0x00,0x00) : QColor(0xDD,0xDD,0xDD),1, Qt::SolidLine)); painter.drawText(cr,QString::number(currentDay),QTextOption(Qt::AlignCenter)); currentDay++; } } painter.setPen(QPen(QColor(0x88,0x88,0x88),1, Qt::SolidLine)); painter.drawRect(r); } #endif // #if (USE_DATE_TIME_LIST)