first commit

This commit is contained in:
2026-02-21 17:11:31 +09:00
commit 18b4338361
4001 changed files with 365464 additions and 0 deletions

View File

@@ -0,0 +1,691 @@
#include "rm_app.h"
//#include "rm_include.h"
#include <Windows.h>
#include <QFont>
#include <QFontDatabase>
#include <QApplication>
#include <QTranslator>
#include <QMainWindow>
#include <QFile>
#include <QStandardPaths>
#include <QDir>
#include <QDebug>
#include <Windows.h>
#include <ShlObj.h>
#include <QTextCodec>
#include <QSettings>
#include <QMainWindow>
#include <QDateTime>
bool RMApp::unsupportedGPU = false;
static QString gOpenFolderTitle;
bool RMApp::isMPH = false;
#if (USER_LOGER)
bool RMApp::userLog = false;
#endif //
#if (USE_MAXIMIZE)
int RMApp::mMAXIMIZE = -1;
#endif // #if (USE_MAXIMIZE)
#if (SUPPORT_LIBRARY_MODE && !PLAYER_ONLY_LIBRARY_MODE)
bool RMApp::isTB5000 = false;
#endif // SUPPORT_LIBRARY_MODE
QString RMApp::currentRoot = "";
#if (RM_MODEL == RM_MODEL_TYPE_TB4000)
#include "module/rm_crypt.h"
//#include "fav/AVPlayer.h"
#define USER_SETTINGS "HKEY_CURRENT_USER\\SOFTWARE\\TB4000_VIEWER"
#define PASSWORD_KEY Q_UINT64_C(0x0c2fd4acacbaf023) // 레지스트리에 암호 저장시 암호화
QString RMApp::password()
{
QSettings settings(USER_SETTINGS,QSettings::NativeFormat);
if(settings.contains("password")) {
QString epw = settings.value("password").toString();
RMCrypt crypto(PASSWORD_KEY);
QString pw = crypto.decryptToString(epw);
//FAV::AVPlayer::setPassword(pw.toLatin1().data());
return pw;
}
return "";
}
bool RMApp::setPassword(QString pw)
{
// 설정저장
//FAV::AVPlayer::setPassword(pw.toLatin1().data()); // "123456789#"
QSettings settings(USER_SETTINGS,QSettings::NativeFormat);
RMCrypt crypto(PASSWORD_KEY);
QString encrypted = crypto.encryptToString(pw);
settings.setValue("password",encrypted);
settings.sync();
// 저장된 패스워드 재확인
return pw == password();
}
#elif (RM_MODEL == RM_MODEL_TYPE_BV2000)
#define USER_SETTINGS "HKEY_CURRENT_USER\\SOFTWARE\\BV2000_VIEWER"
#elif (RM_MODEL == RM_MODEL_TYPE_MH9000)
#define USER_SETTINGS "HKEY_CURRENT_USER\\SOFTWARE\\MH9000_VIEWER"
#elif (RM_MODEL == RM_MODEL_TYPE_EMT_KR)
#define USER_SETTINGS "HKEY_CURRENT_USER\\SOFTWARE\\NEXIAN_VIEWER"
#elif (RM_MODEL == RM_MODEL_TYPE_AN6000)
#define USER_SETTINGS "HKEY_CURRENT_USER\\SOFTWARE\\AN6000_VIEWER"
#endif
QString RMApp::lastPath(QString tag)
{
QSettings settings(USER_SETTINGS,QSettings::NativeFormat);
QString key = "last_path." + tag;
if(settings.contains(key)) {
return settings.value(key).toString();
}
return "";
}
void RMApp::setLastPath(QString tag, QString path)
{
QSettings settings(USER_SETTINGS,QSettings::NativeFormat);
QString key = "last_path." + tag;
settings.setValue(key,path);
settings.sync();
}
#if (USER_LOGER)
void RMApp::appendLog(QString tag, QString log)
{
QString time = QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.z");
userLogs.append(time + "\t" + tag + "\t" + log);
}
void RMApp::saveLog()
{
QString folder = RMApp::appPath(RMApp::REPORT);
QString time =QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
QString dest = QDir::cleanPath(folder + QDir::separator() + SETTINGS_TAG + "_" + time + ".log");
QFile f(dest);
if (f.open(QFile::WriteOnly | QFile::Text)) {
QTextStream s(&f);
s.setCodec("UTF-8");
for (int i = 0; i < userLogs.size(); ++i)
s << userLogs.at(i) << '\n';
} else {
return;
}
f.close();
}
#endif // USER_LOGER
RMApp::RMApp(QObject* parent) : QObject(parent) {
#if (PENTA_CHANNEL)
chMode = ChannelModeFR;
#endif // #if (PENTA_CHANNEL)
#if (DETECT_USB_CHANGE)
usb = NULL; // 메인 윈도우에서 생성
#endif // #if (DETECT_USB_CHANGE)
#if (RM_MODEL == RM_MODEL_TYPE_TB4000)
playPath = "";
#endif // #if (RM_MODEL == RM_MODEL_TYPE_TB4000)
}
#if !(REMOVE_ALL_SHORT_CUTS)
void RMApp::installGlobalShortcuts()
{
// 각자 알아서 connect 함
pipPositionShortcut = new QShortcut(QKeySequence(Qt::Key_F9), pMainWindow);
pipPositionShortcut->setContext(Qt::ApplicationShortcut);
pipToggleShortcut = new QShortcut(QKeySequence(Qt::Key_F10), pMainWindow);
pipToggleShortcut->setContext(Qt::ApplicationShortcut);
}
#endif
void RMApp::initialize(QApplication& appliction)
{
// IE Reg
RMApp::_initIERegistry();
// TEXT CODEC
//QTextCodec::setCodecForLocale(QTextCodec::codecForName("EUC-KR"));
QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
// Font
RMApp::_setSystemFont("MS PGothic",false);
QApplication::font().setStyleStrategy(QFont::PreferAntialias);
// Stylesheet
QFile File(":/stylesheet/style.qss");
if(File.open(QFile::ReadOnly))
{
QString StyleSheet = QLatin1String(File.readAll());
appliction.setStyleSheet(StyleSheet);
}
// Translator
#if !(DO_NOT_USE_TRANSLATOR)
pTranslator = new QTranslator(this);
pTranslator->load("cellstar_ja.qm",":/lang");
appliction.installTranslator(RMApp::instance()->pTranslator);
#endif
// Folder Init
_initDocumentFolder();
// Load Settings
RMSettings::instance()->load();
}
// 이전 폴더 저장
static HWND hOpenFolder = NULL;
int CALLBACK SHBrowseCallbackProc2(HWND hwnd, UINT uMsg,LPARAM lParam, LPARAM lpData)
{
Q_UNUSED(lParam);
switch (uMsg)
{
case BFFM_INITIALIZED:
hOpenFolder = hwnd;
::SetWindowText(hwnd,(LPCWSTR)gOpenFolderTitle.utf16());
::SendMessage( hwnd, BFFM_SETSELECTION, TRUE, lpData );
break;
case BFFM_SELCHANGED:
TCHAR szText[MAX_PATH] = {0};
::SHGetPathFromIDList(reinterpret_cast<LPITEMIDLIST>(lParam), szText);
QString path = QString::fromUtf16((const ushort*)szText);
if(path.length() == 3 && path[1] == ':')
{
QString devicePath = QString("\\\\.\\") + path.at(0) + QString(":");
HANDLE hDevice = ::CreateFile ((LPCWSTR)devicePath.utf16(), // like "\\.\E:"
FILE_READ_ATTRIBUTES, // read access to the attributes
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
::SendMessage( hwnd, BFFM_ENABLEOK, 0, 0 );
}
else
{
DWORD cbBytesReturned;
BOOL bSuccess = ::DeviceIoControl (hDevice, // device to be queried
IOCTL_STORAGE_CHECK_VERIFY2,
NULL, 0, // no input buffer
NULL, 0, // no output buffer
&cbBytesReturned, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
::SendMessage( hwnd, BFFM_ENABLEOK, 0, bSuccess );
::CloseHandle(hDevice);
}
}
break;
}
return 0;
}
void RMApp::closeOpenFolder()
{
if(hOpenFolder != NULL) {
::CloseWindow(hOpenFolder);
hOpenFolder = NULL;
}
}
QString RMApp::openFolder(QString last,bool bCreateNew,QString title)
{
// DeskTop
TCHAR szDir[MAX_PATH] = {0,};
BROWSEINFO bInfo = {0,};
// ファイルOPEN
QString dialogTitle = (title.length() > 0) ? title : MKU8("\xe3\x83\x95\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab\x4f\x50\x45\x4e");
if(title.length() > 0) {
gOpenFolderTitle = title;
}
QString documentPath = QDir::toNativeSeparators(last);//RMSettings::instance()->lastMoviePath();
//QString documentPath = "C:\\home\\testing\\20200902_NEXTEC_SAMPLE\\"; // "C:\\home\\testing\\NEXTEC_\\"; //
//qInfo() << documentPath;
QString dir;
bInfo.hwndOwner = reinterpret_cast<HWND>(RMApp::instance()->pMainWindow->winId());
bInfo.pidlRoot = NULL;
bInfo.pszDisplayName = szDir;
bInfo.lpszTitle = reinterpret_cast<LPCWSTR>(dialogTitle.utf16());
bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;// | BIF_NONEWFOLDERBUTTON;
if(bCreateNew == false) {
bInfo.ulFlags |= BIF_NONEWFOLDERBUTTON;
}
bInfo.lpfn = SHBrowseCallbackProc2;
bInfo.lParam = (LPARAM)(LPCTSTR)documentPath.utf16();;
bInfo.iImage = -1;
LPITEMIDLIST lpItem = ::SHBrowseForFolder(&bInfo);
if( lpItem != NULL )
{
if(::SHGetPathFromIDList(lpItem, szDir ) == TRUE)
{
dir = QString::fromUtf16((const ushort*)szDir);
//qInfo() << "dir:" << dir << QFile::exists(dir);
}
}
IMalloc * imalloc = 0;
if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
{
imalloc->Free ( lpItem );
imalloc->Release ( );
}
// Focus 처리하지 않으면 keypress event 는 발생하지 않는다.
if(RMApp::instance()->pMainWindow != NULL)
{
RMApp::instance()->pMainWindow->setFocus();
}
hOpenFolder = NULL;
return dir;
}
void RMApp::disableScreenSave(bool disable)
{
if (disable == true) {
::SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
}
else {
::SetThreadExecutionState(ES_CONTINUOUS);
}
}
// 비디오 파일 열면 디스크 설정 하도록 한 부분 제거
//QString RMApp::isFolderInRemovableDisk(QString folderPath)
//{
// QStringList lst = folderPath.split(QDir::separator(),QString::SkipEmptyParts);
// if(lst.length() > 0) {
// QString root = lst[0];
// root = root.replace("\\","");
// QStringList list = RMApp::getRemovableDisks();
// foreach (QString eachDisk, list) {
// if(eachDisk.replace("\\","").compare(root,Qt::CaseInsensitive) == 0)
// {
// return root + "\\";
// }
// }
// }
// return "";
//}
#if (MULTI_MODEL_VIEWER)
QList<QPair<QString,QString>> RMApp::searchModelDisk()
{
QStringList ls = getRemovableDisks();
char model_name[128];
QList<QPair<QString,QString>> founds = QList<QPair<QString,QString>>();
foreach (QString disk, ls) {
memset(model_name,0,128);
bool isEMS = false;
if(isModelDisk(disk,&isEMS,model_name))
{
// EMS 는 처리하지 않음
if(!isEMS) {
founds.append(QPair<QString,QString>(disk,model_name));
}
}
}
return founds;
}
bool RMApp::isModelDisk(QString& disk,bool* isEMS,char* pMODEL_NAME)
{
QString cfgPath = QDir::cleanPath(disk + SETTINGS_FILE_NAME);
//LOG_TEST << cfgPath;
if(QFile::exists(cfgPath)){
// 26~31 사이에 0 이 아닌 값이 있을 경우 XDR-88
FILE* f = fopen(cfgPath.toLocal8Bit(),"r+b");
if(f != NULL) {
bool bSuccess = false;
fseek(f,0,SEEK_END);
long sz = ftell(f);
if(sz == 45) {
if(pMODEL_NAME != NULL) {
strcpy(pMODEL_NAME,"XDR-66");
}
bSuccess = true;
}
else if (sz == 0x20) {
if(pMODEL_NAME != NULL) {
strcpy(pMODEL_NAME,"XLDR-88");
}
bSuccess = true;
}
else if (sz == 17) { // EMS 디스크도 일단 탐색은 성공
bSuccess = true;
}
if(isEMS != NULL) {
*isEMS = (sz == 17); // EMS S/W 에서 생성된 차량정보 파일
}
return bSuccess;
}
/*
if(f != NULL) {
char bb[32] = {0,};
bool bXDR88 = false;
fread(bb,1,32,f);
for(int i=26;i<32;i++) {
if(bb[i] != 0) {
bXDR88 = true;
break;
}
}
fclose(f);
if(pMODEL_NAME != NULL) {
if(bXDR88) {
strcpy(pMODEL_NAME,"XLDR-88");
}
else {
strcpy(pMODEL_NAME,"XDR-66");
}
}
return true;
#if (CFG_SEARCH_DISK)
return (strncmp(SETTINGS_TAG,model,strlen(SETTINGS_TAG)) == 0);
#else
return true;
#endif
}
*/
}
return false;
}
#else // MULTI_MODEL_VIEWER
bool RMApp::isModelDisk(QString& disk)
{
QString cfgPath = QDir::cleanPath(disk + SETTINGS_FILE_NAME);
//LOG_TEST << cfgPath;
#if (RM_MODEL == RM_MODEL_TYPE_AN6000)
return QFile::exists(cfgPath);
#else // AN6000 은 파일존재만 확인
if(QFile::exists(cfgPath)){
//qInfo() << cfgPath << "EXIST";
FILE* f = fopen(cfgPath.toLocal8Bit(),"r+b");
if(f != NULL) {
char model[16] = {0,};
fread(model,1,16,f);
//qInfo() << model << "MODEL";
fclose(f);
#if (CFG_SEARCH_DISK)
return (strncmp(SETTINGS_TAG,model,strlen(SETTINGS_TAG)) == 0);
#else
return true;
#endif
}
}
return false;
#endif // #if (RM_MODEL == RM_MODEL_TYPE_AN6000)
}
#endif // MULTI_MODEL_VIEWER
QString RMApp::searchInfoDisk()
{
QStringList list = RMApp::getRemovableDisks();
foreach (QString path, list) {
QString cfgPath = QDir::cleanPath(path + SETTINGS_FILE_NAME);
QString versionPath = QDir::cleanPath(path + "//VERSION.TXT");
if(QFile::exists(cfgPath) &&
QFile::exists(versionPath)) {
FILE* f = fopen(cfgPath.toLocal8Bit(),"r+b");
if(f != NULL)
{
char model[16] = {0,};
fread(model,1,16,f);
fclose(f);
if(strncmp(SETTINGS_TAG,model,strlen(SETTINGS_TAG)) == 0) {
return path;
}
}
return path;
}
}
return "";
}
QStringList RMApp::getRemovableDisks()
{
QStringList disks;
WCHAR szLogicalDrives[MAX_PATH * sizeof(TCHAR)];
DWORD dwByte = ::GetLogicalDriveStrings(MAX_PATH, szLogicalDrives);
for(DWORD i=0; i<dwByte / 4; i++)
{
WCHAR* diskName = &szLogicalDrives[i * 4];
UINT type = ::GetDriveType(diskName);
// qInfo() << "type:" << type << "\ndisk:" << QString::fromUtf16((const ushort*)diskName);
if(DRIVE_REMOVABLE == type)
{
QString diskLetter = QString::fromUtf16((const ushort*)diskName);
diskLetter.replace("\\","");
diskLetter = "\\\\.\\" + diskLetter;
// qInfo() << "check disk name:" << diskLetter;
// empty media check
HANDLE hDisk = ::CreateFile(reinterpret_cast<LPCWSTR>(diskLetter.utf16()),
FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if(hDisk == INVALID_HANDLE_VALUE || hDisk == NULL)
{
//qInfo() << "INVALID_HANDLE_VALUE" << diskLetter << "type" << type;
continue;
}
DWORD dwBytesReturned;
ULONG MediaChangeCount;
BOOL res = ::DeviceIoControl( hDisk,
IOCTL_STORAGE_CHECK_VERIFY,
NULL,
0,
&MediaChangeCount,
sizeof(ULONG),
&dwBytesReturned,
NULL);
::CloseHandle(hDisk);
if(res == FALSE)
{
//qInfo() << "empty" << QString::fromUtf16((const ushort*)diskName) << "type" << type;
continue;
}
WCHAR volumeNameW[MAX_PATH * sizeof(TCHAR)] = {0,};
::GetVolumeInformation(diskName,volumeNameW, 1024, NULL, NULL, NULL, NULL, MAX_PATH);
QString diskPath = QString::fromUtf16((const ushort*)diskName);
diskPath = diskPath.replace("\\","");
disks.append(diskPath);
// qInfo() << "disk path:" << diskPath;
// return diskPath;
}
}
return disks;
}
bool RMApp::checkGPU()
{
const QStringList blackList = QStringList() << "G41" << "GM45" << "G45" << "GS45" << "GL40" << "Q45" << "Q43" << "X4500";
DISPLAY_DEVICE dd;
dd.cb = sizeof(DISPLAY_DEVICE);
DWORD deviceNum = 0;
while(::EnumDisplayDevices(NULL, deviceNum, &dd, NULL) )
{
QString deviceString = QString::fromUtf16((const ushort*)dd.DeviceString);
deviceString = deviceString.replace(" ","").toUpper();
foreach (QString name, blackList)
{
if (deviceString.contains(name) == true)
{
RMApp::unsupportedGPU = true;
return true;
}
}
//qDebug() << "DeviceName" << QString::fromUtf16((const ushort*)dd.DeviceName);
//qDebug() << "DeviceString" << deviceString;
deviceNum++;
}
return false;
}
QString RMApp::appPath(RMApp::Path type)
{
QString sub;
switch (type) {
case REPORT:
sub = "report";
break;
case INI:
// viewersetup
#if (MODEL_STANDARD)
#if defined(_WIN64)
sub = QString("viewersetup") + QDir::separator() + QString("conf64.ini");
#else
sub = QString("viewersetup") + QDir::separator() + QString("conf.ini");
#endif
#endif
#if (MODEL_BBVIEWER)
sub = QString("viewersetup") + QDir::separator() + QString("conf_fd500.ini");
#endif
//sub = QString("BBConfig") + QDir::separator() + QString("conf.ini");
break;
case CAPTURE:
sub = "backup";
break;
#if (RM_TESTING)
case SCRIPT:
sub = "script";
break;
#endif
default:
break;
}
if(sub.isEmpty() == false)
{
QString document = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
return QDir::cleanPath(document + QDir::separator() + ROOT_DOCUMENT_NAME + QDir::separator() + sub);
}
return "";
}
void RMApp::_initIERegistry()
{
//qInfo() << "_initIERegistry" << __FUNCTION__;
// 사용할 IE 버전 등록
const QString regAddr = "HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION\\";
const QString key = QFileInfo(QCoreApplication::applicationFilePath()).fileName();//QString(TARGET_NAME) + ".exe";
QSettings settings(regAddr,QSettings::NativeFormat);
if(true) { //settings.contains(key) == false) {
//
//const QVariant dv((uint)12001); // REAL EDGE
const QVariant dv((uint)11001);
//const QVariant dv((uint)11000);
settings.setValue(key,dv);
}
//64 bits: [(HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE)\Software\wow6432node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
//"DesignU.exe" = dword 11000 (Hex: 0x2af8)
}
void RMApp::_initDocumentFolder()
{
// 추가 폴더 생성 금지
QString document = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QStringList dirList = QStringList() << "backup" << "viewersetup" << "report";
#if (RM_TESTING)
dirList << "script";
#endif
if(QDir(document).exists())
{
QString root = QDir::cleanPath(document + QDir::separator() + ROOT_DOCUMENT_NAME);
if(QDir(root).exists() == false)
{
QDir().mkdir(root);
}
foreach (QString eachDir, dirList) {
QString eachAbsoluteDir = QDir::cleanPath(root + QDir::separator() + eachDir);
if(QDir(eachAbsoluteDir).exists() == false)
{
QDir().mkdir(eachAbsoluteDir);
//qDebug() << eachAbsoluteDir;
}
}
}
}
void RMApp::_setSystemFont(const char* fontName, bool res)
{
QFontDatabase db;
bool found = false;
// LOAD LCD FONT
int id = QFontDatabase::addApplicationFont(":/font/alarmclock2.ttf");
Q_UNUSED(id)
// QString family = QFontDatabase::applicationFontFamilies(id).at(0);
// qInfo() << "font:" << family;
if(res == false) {
foreach (QString family, db.families()) {
if(family == QString(fontName)) {
found = true;
break;
}
}
if(found) {
QFont font(fontName);
font.setStyleHint(QFont::System);
font.setStyleStrategy(QFont::PreferAntialias);
QApplication::setFont(font);
}
}
else {
// http://mplus-fonts.osdn.jp/design.html#mplus_1
// mplus-1p-regular.ttf
// mplus-1p-bold.ttf
// mplus-1p-medium.ttf
int id = QFontDatabase::addApplicationFont(":/font/" + QString(fontName));
QString family = QFontDatabase::applicationFontFamilies(id).at(0);
QFont font(family,QFont::System); // , true
font.setStyleHint(QFont::System);
font.setStyleStrategy(QFont::PreferAntialias);
QApplication::setFont(font);
}
}