#ifndef RM_VIDEOFILELIST_H #define RM_VIDEOFILELIST_H #include #include #include #include #include #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 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& res); //! \brief 전달된 item 에 속하는 모든 RMVideoItem 추출 //! - Thumbnail 에서 사용 //! \param dt : 탐색할 아이템 시간 //! \param res : 결과 void load1HourInList(QDateTime dt, QList& res); //! \brief RMVideoItem 리스트 에서 썸네일 경로 추출 //! \param src : 추출할 VideoItem 리스트 //! \param res : Thumbnail 경로 void loadThumbnails(QList& src, QList>& res); #endif // USE_1HOUR_FILTER #if (USE_DATE_TIME_LIST) //! \brief 파일리스트 중 지정된 년/월 에 영상인 포함된 날짜만 리턴 //! \param year: 지정된 년 //! \param month: 지정된 월 //! \param ret: 영상이 존재하는 일 리스트 //! \param dayItems: 속도개선을 위해 해당일자의 파일리스트 리턴 void getMonthList(int year, int month, QSet& ret, QList& 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 _items; // 전체 아이템 QList _filteredItems; // 필터 적용된 아이템 #if !(USE_1HOUR_FILTER) void _updateItemsByFilter(); // 필터 적용 후 #endif // #if (USE_1HOUR_FILTER) #if !(RECURSIVE_APPEND_FILE) static void _appendFrontRear(QString& folder,QList& 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 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& allItems() { return _items; } QList& filteredItems() { return _filteredItems; } void checkedItems(QList& 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 getThumbnailPath(RMVideoItem* item); static bool isRootPath(QString folderPath); int removeItem(RMVideoItem* item); // 플레이중 삭제 등으로 사라진 아이템 제거 // List.appendToList #if (RECURSIVE_APPEND_FILE) static void appendFolderToList(QString rootFolderPath,QList& list,int depth=0); #else static void appendFolderToList(QString rootFolderPath,QList& list); // Group.appendToList static void appendToList(QString folderPath,QList& 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