Files
fmviewer3/project/fm_viewer/data/rm_video_list.h
2026-02-21 17:11:31 +09:00

436 lines
13 KiB
C++

#ifndef RM_VIDEOFILELIST_H
#define RM_VIDEOFILELIST_H
#include <QObject>
#include <QUrl>
#include <qstring.h>
#include <QMainWindow>
#include <QDebug>
#include "../rm_include.h"
class RMVideoItem;
// #include "rm_video_group.h"
class RMVideoFileList : public QObject
{
Q_OBJECT
public:
friend class RMWidgetVideoListDelegate;
friend class RMWidgetVideoList;
friend class RMVideoFileListLoader;
friend class RMVideoFileListBackup;
static int n_lastPercent;
static QList<QString> fileFilters;
#if (SUPPORT_LOADING_CANCEL)
// 로딩 취소
bool bCancelLoading;
#endif
// item 으로 이동
typedef enum
{
// 주행 / 주행 이벤트 / 주차 / 주차 충격 / 수동 녹화( / 보관함???)
#if (RM_MODEL_EMT_KR)
FILTER_NONE = 0,
FILTER_NORMAL = 1 << 0, // 주행
FILTER_EVENT = 1 << 1, // 주행 이벤트
FILTER_PARK = 1 << 2, // 주차
FILTER_PARK_EVENT = 1 << 3, // 주차 충격
FILTER_MANUAL = 1 << 4, // 수동 녹화
FILTER_MYBOX = 1 << 5, // 보관함 (포함된 폴더가 MYBOX 일 경우 분류 관계없이)
#else // RM_MODEL_EMT_KR
FILTER_NONE = 0,
FILTER_NORMAL = 1 << 0,
FILTER_EVENT = 1 << 1,
#if ((RM_MODEL == RM_MODEL_TYPE_XLDR_88 || SUB_MODEL_CARROT_EMT) || \
RM_MODEL == RM_MODEL_TYPE_BV2000 || \
RM_MODEL == RM_MODEL_TYPE_KEIYO1 || \
RM_MODEL == RM_MODEL_TYPE_TBD360 || \
RM_MODEL == RM_MODEL_TYPE_MBJ5010 || \
RM_MODEL == RM_MODEL_TYPE_MH9000 || \
RM_MODEL == RM_MODEL_TYPE_FC_DR232W)
FILTER_PARK = 1 << 2,
#endif // 주차 사용
#if (RM_MODEL == RM_MODEL_TYPE_KEIYO1 ||\
RM_MODEL == RM_MODEL_TYPE_BV2000 || \
RM_MODEL == RM_MODEL_TYPE_MH9000 || \
RM_MODEL == RM_MODEL_TYPE_MBJ5010 ||\
RM_MODEL == RM_MODEL_TYPE_FC_DR232W)
FILTER_MANUAL = 1 << 3,
FILTER_ALL = FILTER_NORMAL | FILTER_EVENT | FILTER_PARK | FILTER_MANUAL,
#elif (RM_MODEL == RM_MODEL_TYPE_XLDR_88 || SUB_MODEL_CARROT_EMT || RM_MODEL == RM_MODEL_TYPE_MH9000 )
FILTER_ALL = FILTER_NORMAL | FILTER_EVENT | FILTER_PARK,
#elif !(RM_MODEL == RM_MODEL_TYPE_TBD360)
FILTER_ALL = FILTER_NORMAL | FILTER_EVENT,
#endif
#endif // RM_MODEL_EMT_KR
} FILTER;
// 단말기 별로 설정 가능
typedef enum
{
TYPE_NORMAL = 0,
TYPE_EVENT = 1,
TYPE_MANUAL = 2,
TYPE_PARKING = 3,
TYPE_PARKING_EVENT = 4,
TYPE_PARKING_MOTION = 5,
#if (RM_MODEL_EMT_KR)
TYPE_MY_BOX = 6,
#endif // #if (RM_MODEL_EMT_KR)
TYPE_UNDEFINED = 9999,
} GROUP_TYPE;
#if (RM_MODEL == RM_MODEL_TYPE_AN6000)
void removeTemps();
#endif //
#if (RM_MODEL_EMT_KR)
static RMVideoFileList::GROUP_TYPE parseName(QString baseName, QDateTime* dateTime, int* tag);
#endif
#if (USE_1HOUR_FILTER)
//! \brief 1시간 단위 필터 설정
//! \param b1Hour true: 1시간 단위 표시, false: 전체 표시
//! \param bEmit: listUpdateEnd 발생여부
void set1HourList(bool b1Hour, bool bEmit, RMVideoItem* selected);
bool get1HourList()
{
return b1HourList;
}
//! \brief 시간순, 최신순으로 정렬
//! \param bAsc: true: 시간순
void setSortList(bool bAsc);
bool getSortList()
{
return bSortDsc;
}
bool bSortDsc; // 시간순으로 정렬, 최신순으로 정렬
//! \brief 전체 항목에서 1시간 항목 추출
//! \param res : 결과
void load1HourList(QList<RMVideoItem*>& res);
//! \brief 전달된 item 에 속하는 모든 RMVideoItem 추출
//! - Thumbnail 에서 사용
//! \param dt : 탐색할 아이템 시간
//! \param res : 결과
void load1HourInList(QDateTime dt, QList<RMVideoItem*>& res);
//! \brief RMVideoItem 리스트 에서 썸네일 경로 추출
//! \param src : 추출할 VideoItem 리스트
//! \param res : Thumbnail 경로 <CH1,CH2>
void loadThumbnails(QList<RMVideoItem*>& src, QList<QPair<QString,QString>>& res);
#endif // USE_1HOUR_FILTER
#if (USE_DATE_TIME_LIST)
//! \brief 파일리스트 중 지정된 년/월 에 영상인 포함된 날짜만 리턴
//! \param year: 지정된 년
//! \param month: 지정된 월
//! \param ret<out>: 영상이 존재하는 일 리스트
//! \param dayItems<out>: 속도개선을 위해 해당일자의 파일리스트 리턴
void getMonthList(int year, int month, QSet<int>& ret, QList<RMVideoItem*>& dayItems);
//! \brief 로딩된 파일 중 가장 먼저 녹화된 날짜 확인
//! \return
QDate getFirstDate();
#endif// USE_DATE_TIME_LIST
#ifdef _DEBUG
void print();
#endif
#if !(USE_1HOUR_FILTER)
//! \brief 백업용으로 선택된 항목 초기화
void clearChecked();
#endif // #if !(USE_1HOUR_FILTER)
private:
#if (USE_1HOUR_FILTER)
bool b1HourList; // 1시간 단위 리스트
public:
int count1Hour; // 텍스트 표시용
//! \brief 데이터 로딩 후 All 및 1Hour 영상 개수 확인
void count1HourItems();
QDateTime simpleFromDateTime(QDateTime& startTime);
//! \brief 리스트 텍스트 색사용
//! \param startTime
//! \return
QDateTime simpleFromDateTime2(QDateTime& startTime);
private:
//! \brief 현재 선택된 아이템이 전체<->1HOUR 리스트 전환시 유지
//! \param searchItem: 현재 선택된 아이템
//! \return 이후 선택될 아이템
RMVideoItem* findFirstItemIn1Hour(RMVideoItem* searchItem);
#endif // #if (USE_1HOUR_FILTER)
QList<RMVideoItem*> _items; // 전체 아이템
QList<RMVideoItem*> _filteredItems; // 필터 적용된 아이템
#if !(USE_1HOUR_FILTER)
void _updateItemsByFilter(); // 필터 적용 후
#endif // #if (USE_1HOUR_FILTER)
#if !(RECURSIVE_APPEND_FILE)
static void _appendFrontRear(QString& folder,QList<QUrl>& list);
#endif
#if (!(FORCE_2CH) && (!SINGLE_CH_VIEWER))
#if (TRI_CHANNEL || PENTA_CHANNEL)
QString _checkChannelInfo(QString filePath,int *ch);
#else // TRI_CHANNEL
QString _checkChannelInfo(QString filePath,bool *isCH2, bool *is2CH = NULL);
#endif // TRI_CHANNEL
bool _addOtherChannelFile(RMVideoItem* item);
#endif
void _backupOverwrite(QString target,QString src,int countLeft);
public:
void loadFromList(QList<QUrl> list,bool bPlayFirstAdded = false);
//! \brief 리스트 삭제하고 이벤트 전달
void clearList();
//! \brief item 존재할 경우 파일 재생
//! \param item: 재생할 item
void playItem(RMVideoItem* item);
//! \brief 파일 경로로 item 탐색
//! \param path : 탐색할 경로
//! \return
RMVideoItem* itemWithPath(QString path);
//!
//! \brief 파일 로딩 후 선택된 녹화타입 확인용
//! 현재 선택된 필터의 INDEX 를 리턴
//!
int currentFilterIndex();
protected:
int _filter;
RMVideoItem* _playItem; // 현재 플레이 아이템
void backup(QString dest); // 보존
bool addItem(QString filePath, QDateTime* pDateTime,GROUP_TYPE type);
bool itemExist(QString filePath);
// List Widget 에서만 호출 할 수 있도록 변경
void setPlayItem(RMVideoItem* item)
{
_playItem = item;
}
public:
explicit RMVideoFileList(QObject* parent = 0);
//! \brief 파일 시작명으로 재생 아이템 탐색
//! \param prefix: eg. 20231007-040556_PSR0_0017
//! \return 탐색된 재생 리스트 아이템 , 없으면 NULL
RMVideoItem* searchPlayItem(QString prefix);
static FILTER filterTypeFromGroupType(GROUP_TYPE type)
{
FILTER t = FILTER_NONE;
switch (type) {
#if (RM_MODEL == RM_MODEL_TYPE_XLDR_88)
case TYPE_NORMAL:
case TYPE_MANUAL:
t = FILTER_NORMAL;
break;
case TYPE_EVENT:
case TYPE_PARKING_EVENT:
case TYPE_PARKING_MOTION:
t = FILTER_EVENT;
break;
case TYPE_PARKING:
t = FILTER_PARK;
break;
}
#elif (RM_MODEL == RM_MODEL_TYPE_KEIYO1 || RM_MODEL == RM_MODEL_TYPE_MBJ5010 || RM_MODEL == RM_MODEL_TYPE_FC_DR232W || RM_MODEL == RM_MODEL_TYPE_BV2000 || RM_MODEL == RM_MODEL_TYPE_MH9000)
case TYPE_NORMAL:
t = FILTER_NORMAL;
break;
//#if !(RM_MODEL == RM_MODEL_TYPE_MH9000)
case TYPE_MANUAL:
t = FILTER_MANUAL;
break;
//#endif // RM_MODEL == RM_MODEL_TYPE_MH9000
case TYPE_PARKING:
case TYPE_PARKING_EVENT:
t = FILTER_PARK;
break;
case TYPE_EVENT:
case TYPE_PARKING_MOTION:
t = FILTER_EVENT;
break;
}
#elif (RM_MODEL_EMT_KR)
case TYPE_NORMAL:
t = FILTER_NORMAL;
break;
case TYPE_EVENT:
t = FILTER_EVENT;
break;
case TYPE_PARKING:
t = FILTER_PARK;
break;
case TYPE_PARKING_EVENT:
t = FILTER_PARK_EVENT;
break;
case TYPE_MANUAL:
t = FILTER_MANUAL;
break;
case TYPE_MY_BOX:
t = FILTER_MYBOX;
break;
}
#else
case TYPE_NORMAL:
t = FILTER_NORMAL;
break;
case TYPE_EVENT:
case TYPE_PARKING_EVENT:
case TYPE_PARKING_MOTION:
t = FILTER_EVENT;
break;
}
#endif
return t;
}
QList<RMVideoItem*>& allItems() { return _items; }
QList<RMVideoItem*>& filteredItems()
{
return _filteredItems;
}
void checkedItems(QList<RMVideoItem*>& items);
#if (PLAYER_ONLY_LIBRARY_MODE)
static RMVideoFileList * _instance;
static void updateInstance(RMVideoFileList* instance)
{
_instance = instance;
}
static RMVideoFileList* instance()
{
return _instance;
}
#else // PLAYER_ONLY_LIBRARY_MODE
// singletone
static RMVideoFileList* instance()
{
static RMVideoFileList * _instance = 0;
if ( _instance == 0 ) {
_instance = new RMVideoFileList();
}
return _instance;
}
#endif // PLAYER_ONLY_LIBRARY_MODE
#if (RM_MODEL_EMT_KR)
/**
* @brief 로딩된 파일 중 가장 많은 파일이 존재하는 녹화타입 선택
*/
void selectMaxCountFilter();
#endif // RM_MODEL_EMT_KR
#if !(USE_1HOUR_FILTER)
bool checkFilter(RMVideoFileList::FILTER filter)
{
return ((_filter & filter) == filter);
}
void setFilter(RMVideoFileList::FILTER filter, bool on);
void setFilterSingle(RMVideoFileList::FILTER filter);
#endif // #if !(USE_1HOUR_FILTER)
RMVideoItem* getPlayItem() // 현재 플레이 중이면 다시 플레이 하지 않는다.
{
return _playItem;
}
int getPlayIndex() // 현재 그룹에서 플레이 중인 인덱스 리턴
{
if(_playItem == NULL)
{
return -1;
}
return filteredItems().indexOf(_playItem);
}
//! \brief 영상 경로를 썸네일 경로로 변경
//! \param item: 추출할 아이템
//! \return
static QPair<QString,QString> getThumbnailPath(RMVideoItem* item);
static bool isRootPath(QString folderPath);
int removeItem(RMVideoItem* item); // 플레이중 삭제 등으로 사라진 아이템 제거
// List.appendToList
#if (RECURSIVE_APPEND_FILE)
static void appendFolderToList(QString rootFolderPath,QList<QUrl>& list,int depth=0);
#else
static void appendFolderToList(QString rootFolderPath,QList<QUrl>& list);
// Group.appendToList
static void appendToList(QString folderPath,QList<QUrl>& list, bool baseFolderOnly);
#endif
static RMVideoFileList::GROUP_TYPE checkGroupTypeFromFolderPath(QString folderPath);
#if (RM_MODEL == RM_MODEL_TYPE_AN6000)
static int parseSerial(QString baseName);
static QString groupTypeFromFilePath(QString filePath,RMVideoFileList::GROUP_TYPE* type, int* serial);
#else // RM_MODEL_TYPE_AN6000
static QString groupTypeFromFilePath(QString filePath,RMVideoFileList::GROUP_TYPE* type);
#endif // RM_MODEL_TYPE_AN6000
bool isNextPlayItemExist(bool bNext);
RMVideoItem* nexItem(bool bNext);
private:
bool _searchItem(bool next, RMVideoItem** item,int fromIndex); // 탐색 next = +1, previous = -1
public slots:
void onPlayNextVideo(int fromIndex);
void onPlayPreviousVideo(int fromIndex);
signals:
// 리스트 업데이트 시작(파일 로딩 또는 필터 변경시 호출)
void listUpdateStarted(bool bLoading);
void listUpdateEnd(bool bLoading,RMVideoItem* selected);
// 리스트의 경우 타입이 변경되어도 이벤트가 발생하니 로딩 종료시에만 처리
void loadListEnd();
void backupStarted();
void backupEnd();
void backupPaused(bool bPaused);
// 다음 플레이 아이템 확인, 더이상 없음
void playItemFound(RMVideoItem* item,int old);
void playNoMoreItem();
void updateProgress(int value);
};
#endif // RM_VIDEOFILELIST_H