From dee19de15c45db3d1144127f2a5dd0074a50dc07 Mon Sep 17 00:00:00 2001 From: Brian Ferguson Date: Thu, 28 Feb 2013 09:15:28 -0700 Subject: [PATCH] FileView: Added Recursive=2 option. Commands FollowPath and PreviousFolder do not work with this option. Also, ShowFile, ShowFolder, and ShowDotDot have no effect on this option. Drives are now sorted. Folders have dates and times. Lots of tweaks and cleanup. Updated to version 2. --- Plugins/PluginFileView/PluginFileView.cpp | 574 ++++++++++++---------- Plugins/PluginFileView/PluginFileView.h | 202 ++------ Plugins/PluginFileView/PluginFileView.rc | 4 +- Plugins/PluginFileView/StdAfx.h | 2 +- 4 files changed, 358 insertions(+), 424 deletions(-) diff --git a/Plugins/PluginFileView/PluginFileView.cpp b/Plugins/PluginFileView/PluginFileView.cpp index a0bb0ec8..2d3878b2 100644 --- a/Plugins/PluginFileView/PluginFileView.cpp +++ b/Plugins/PluginFileView/PluginFileView.cpp @@ -44,9 +44,9 @@ typedef struct // 22 bytes #pragma pack(pop) unsigned __stdcall SystemThreadProc(void* pParam); -void GetSubFolderSize(const std::vector files, const std::wstring path, int& folderCount, int& fileCount, UINT64& folderSize); -void GetIcon(std::wstring fileName, std::wstring iconPath, IconSize iconSize); -HRESULT SaveIcon(HICON icon, FILE*fp); +void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType); +void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize); +HRESULT SaveIcon(HICON hIcon, FILE* fp); std::vector g_ParentMeasures; static CRITICAL_SECTION g_CriticalSection; @@ -87,12 +87,12 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { path = path.substr(1, path.size() - 2); - for (auto iter = g_ParentMeasures.begin(); iter != g_ParentMeasures.end(); ++iter) + for (auto iter : g_ParentMeasures) { - if (_wcsicmp((*iter)->name, path.c_str()) == 0 && - (*iter)->skin == skin) + if (_wcsicmp(iter->name, path.c_str()) == 0 && + iter->skin == skin) { - child->parent = (*iter); + child->parent = iter; break; } } @@ -157,14 +157,32 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) int count = RmReadInt(rm, L"Count", 1); child->parent->count = count > 0 ? count : 1; - child->parent->isRecursive = 0!=RmReadInt(rm, L"Recursive", 0); + int recursive = RmReadInt(rm, L"Recursive", 0); + switch (recursive) + { + default: + RmLog(LOG_WARNING, L"Invalid Recursive type"); + + case 0: + child->parent->recursiveType = RECURSIVE_NONE; + break; + + case 1: + child->parent->recursiveType = RECURSIVE_PARTIAL; + break; + + case 2: + child->parent->recursiveType = RECURSIVE_FULL; + break; + } + child->parent->sortAscending = 0!=RmReadInt(rm, L"SortAscending", 1); child->parent->showDotDot = 0!=RmReadInt(rm, L"ShowDotDot", 1); child->parent->showFile = 0!=RmReadInt(rm, L"ShowFile", 1); child->parent->showFolder = 0!=RmReadInt(rm, L"ShowFolder", 1); child->parent->showHidden = 0!=RmReadInt(rm, L"ShowHidden", 1); child->parent->showSystem = 0!=RmReadInt(rm, L"ShowSystem", 0); - child->parent->hideExtension = 0!=RmReadInt(rm, L"HideExtensions", 0); + child->parent->hideExtension = 0!=RmReadInt(rm, L"HideExtensions", 0); child->parent->extensions = Tokenize(RmReadString(rm, L"Extensions", L""), L";"); child->parent->wildcardSearch = RmReadString(rm, L"WildcardSearch", L"*"); @@ -172,12 +190,6 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) child->parent->finishAction = RmReadString(rm, L"FinishAction", L"", false); } - auto iter = std::find(child->parent->children.begin(), child->parent->children.end(), child); - if (iter == child->parent->children.end()) - { - child->parent->children.push_back(child); - } - int index = RmReadInt(rm, L"Index", 1) - 1; child->index = index >= 0 ? index : 1; @@ -238,7 +250,7 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) WCHAR buffer[MAX_PATH]; _itow_s(child->index + 1, buffer, 10); temp += buffer; - temp += L".ico"; + temp += L".ico"; child->iconPath = RmReadPath(rm, L"IconPath", temp.c_str()); LPCWSTR size = RmReadString(rm, L"IconSize", L"MEDIUM"); @@ -258,6 +270,12 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { child->iconSize = IS_EXLARGE; } + + auto iter = std::find(child->parent->iconChildren.begin(), child->parent->iconChildren.end(), child); + if (iter == child->parent->iconChildren.end()) + { + child->parent->iconChildren.push_back(child); + } } else if (_wcsicmp(type, L"FILEPATH") == 0) { @@ -279,22 +297,22 @@ PLUGIN_EXPORT double Update(void* data) if (parent->ownerChild == child && (parent->needsUpdating || parent->needsIcons)) { unsigned int id; - HANDLE thread = (HANDLE)_beginthreadex(NULL, 0, SystemThreadProc, child, 0, &id); + HANDLE thread = (HANDLE)_beginthreadex(nullptr, 0, SystemThreadProc, parent, 0, &id); if (thread) { parent->thread = thread; } } - + int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); - child->value = 0; + double value = 0; if (!parent->files.empty() && trueIndex >= 0 && trueIndex < parent->files.size()) { switch (child->type) { case TYPE_FILESIZE: - child->value = parent->files[trueIndex].size > 0 ? (double)parent->files[trueIndex].size : 0; + value = parent->files[trueIndex].size > 0 ? (double)parent->files[trueIndex].size : 0; break; case TYPE_FILEDATE: @@ -319,42 +337,42 @@ PLUGIN_EXPORT double Update(void* data) } FileTimeToSystemTime(&fTime, &stUTC); - SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLOCAL); + SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); SystemTimeToFileTime(&stLOCAL, &fTime); time.LowPart = fTime.dwLowDateTime; time.HighPart = fTime.dwHighDateTime; - child->value = (double)(time.QuadPart / 10000000); + value = (double)(time.QuadPart / 10000000); } break; } } - + switch (child->type) { case TYPE_FILECOUNT: - child->value = (double)parent->fileCount; + value = (double)parent->fileCount; break; case TYPE_FOLDERCOUNT: - child->value = (double)parent->folderCount; + value = (double)parent->folderCount; break; case TYPE_FOLDERSIZE: - child->value = (double)parent->folderSize; + value = (double)parent->folderSize; break; } LeaveCriticalSection(&g_CriticalSection); - return child->value; + return value; } PLUGIN_EXPORT LPCWSTR GetString(void* data) { ChildMeasure* child = (ChildMeasure*)data; ParentMeasure* parent = child->parent; - + EnterCriticalSection(&g_CriticalSection); if (!parent) { @@ -373,7 +391,7 @@ PLUGIN_EXPORT LPCWSTR GetString(void* data) if (!parent->files[trueIndex].isFolder) { LeaveCriticalSection(&g_CriticalSection); - return NULL; // Force a numeric return (see the Update function) + return nullptr; // Force a numeric return (see the Update function) } break; @@ -423,11 +441,11 @@ PLUGIN_EXPORT LPCWSTR GetString(void* data) if (fTime.dwLowDateTime != 0 && fTime.dwHighDateTime != 0) { FileTimeToSystemTime(&fTime, &stUTC); - SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLOCAL); - GetDateFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, NULL, temp, MAX_LINE_LENGTH); + SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); + GetDateFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); child->strValue = temp; child->strValue += L" "; - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, NULL, temp, MAX_LINE_LENGTH); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); child->strValue += temp; } else @@ -443,7 +461,7 @@ PLUGIN_EXPORT LPCWSTR GetString(void* data) break; case TYPE_FILEPATH: - child->strValue = (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) ? parent->path : parent->path + parent->files[trueIndex].fileName; + child->strValue = (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) ? parent->path : parent->files[trueIndex].path + parent->files[trueIndex].fileName; break; } } @@ -453,9 +471,8 @@ PLUGIN_EXPORT LPCWSTR GetString(void* data) case TYPE_FILECOUNT: case TYPE_FOLDERCOUNT: case TYPE_FOLDERSIZE: - child->strValue = L""; LeaveCriticalSection(&g_CriticalSection); - return NULL; // Force numeric return (see the Update function) + return nullptr; // Force numeric return (see the Update function) break; case TYPE_FOLDERPATH: @@ -478,7 +495,7 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) LeaveCriticalSection(&g_CriticalSection); return; } - + if (parent->ownerChild == child) { if (parent->files.size() > parent->count) @@ -536,14 +553,14 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) } } } - + if (_wcsicmp(args, L"UPDATE") == 0) { parent->indexOffset = 0; parent->needsIcons = true; parent->needsUpdating = true; } - else if (_wcsicmp(args, L"PREVIOUSFOLDER") == 0) + else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"PREVIOUSFOLDER") == 0) { std::vector path = Tokenize(parent->path, L"\\"); if (path.size() < 2) @@ -571,13 +588,13 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); if (!parent->files.empty() && trueIndex >= 0 && trueIndex < parent->files.size()) - { + { if (_wcsicmp(args, L"OPEN") == 0) { - std::wstring file = parent->path + parent->files[trueIndex].fileName; - ShellExecute(NULL, NULL, file.c_str(), NULL, parent->path.c_str(), SW_SHOW); + std::wstring file = parent->files[trueIndex].path + parent->files[trueIndex].fileName; + ShellExecute(nullptr, nullptr, file.c_str(), nullptr, parent->files[trueIndex].path.c_str(), SW_SHOW); } - else if (_wcsicmp(args, L"FOLLOWPATH") == 0) + else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"FOLLOWPATH") == 0) { if (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) { @@ -615,7 +632,7 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) else { std::wstring file = parent->path + parent->files[trueIndex].fileName; - ShellExecute(NULL, NULL, file.c_str(), NULL, parent->path.c_str(), SW_SHOW); + ShellExecute(nullptr, nullptr, file.c_str(), nullptr, parent->path.c_str(), SW_SHOW); } } @@ -636,13 +653,13 @@ PLUGIN_EXPORT void Finalize(void* data) if (parent->thread) { TerminateThread(parent->thread, 0); - parent->thread = NULL; + parent->thread = nullptr; } if (parent && parent->ownerChild == child) { CloseHandle(parent->thread); - parent->thread = NULL; + parent->thread = nullptr; delete parent; @@ -656,52 +673,29 @@ PLUGIN_EXPORT void Finalize(void* data) unsigned __stdcall SystemThreadProc(void* pParam) { - ChildMeasure* child = (ChildMeasure*)pParam; - ParentMeasure* parent = child->parent; + ParentMeasure* parent = (ParentMeasure*)pParam; EnterCriticalSection(&g_CriticalSection); - const bool needsUpdating = parent->needsUpdating; + ParentMeasure* tmp = new ParentMeasure (*parent); parent->needsUpdating = false; // Set to false here in case skin is reloaded - const bool needsIcons = parent->needsIcons; parent->needsIcons = false; // Set to false here in case skin is reloaded - - const std::wstring parentPath = parent->path; - const std::wstring wildcard = parent->wildcardSearch; - const std::vector extensions = parent->extensions; - const bool isRecursive = parent->isRecursive; - const bool showDotDot = parent->showDotDot; - const bool showFile = parent->showFile; - const bool showFolder = parent->showFolder; - const bool showHidden = parent->showHidden; - const bool showSystem = parent->showSystem; - const SortType sortType = parent->sortType; - const DateType sortDateType = parent->sortDateType; - const bool sortAscending = parent->sortAscending; - const std::vector children = parent->children; - - std::vector files = parent->files; - int fileCount = parent->fileCount; - int folderCount = parent->folderCount; - UINT64 folderSize = parent->folderSize; LeaveCriticalSection(&g_CriticalSection); - - std::wstring path = parentPath + wildcard; FileInfo file; - if (needsUpdating) + if (tmp->needsUpdating) { - fileCount = 0; - folderCount = 0; - folderSize = 0; - EnterCriticalSection(&g_CriticalSection); parent->files.clear(); - files.clear(); LeaveCriticalSection(&g_CriticalSection); + tmp->files.clear(); + tmp->fileCount = 0; + tmp->folderCount = 0; + tmp->folderSize = 0; + // If no path is specified, get all the drives instead - if (parentPath == L"" || parentPath.empty()) + if (tmp->path == L"" || tmp->path.empty()) { WCHAR drive[4] = L" :\\"; DWORD driveMask = GetLogicalDrives(); @@ -713,241 +707,295 @@ unsigned __stdcall SystemThreadProc(void* pParam) file.fileName = drive; file.isFolder = true; file.size = 0; - ++folderCount; - files.push_back(file); + ++tmp->folderCount; + tmp->files.push_back(file); } } } else { - if (showDotDot) + if (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL) { file.fileName = L".."; file.isFolder = true; - files.push_back(file); + tmp->files.push_back(file); } - WIN32_FIND_DATA fd; - HANDLE find = FindFirstFileEx(path.c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, 0); + std::queue folderQueue; + std::wstring folder = tmp->path; + + RecursiveType rType = tmp->recursiveType; + GetFolderInfo(folderQueue, folder, tmp, (rType == RECURSIVE_PARTIAL) ? RECURSIVE_NONE : rType); - if (find != INVALID_HANDLE_VALUE) + if (rType != RECURSIVE_NONE) { - do - { - file.Clear(); - - file.fileName = fd.cFileName; - if (_wcsicmp(file.fileName.c_str(), L".") == 0 || _wcsicmp(file.fileName.c_str(), L"..") == 0) + while (!folderQueue.empty()) { - continue; + folder = folderQueue.front(); + GetFolderInfo(folderQueue, folder, tmp, rType); + folderQueue.pop(); } - - file.isFolder = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; - bool isHidden = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) > 0; - bool isSystem = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) > 0; - - if ((!showFile && !file.isFolder) || (!showFolder && file.isFolder) || - (!showHidden && isHidden) || (!showSystem && isSystem)) - { - continue; - } - - if (!file.isFolder) - { - size_t pos = file.fileName.find_last_of(L"."); - if (pos != file.fileName.npos) - { - file.ext = file.fileName.substr(pos + 1); - - if (extensions.size() > 0) - { - bool found = false; - for (auto iter = extensions.begin(); iter != extensions.end(); ++iter) - { - if (_wcsicmp((*iter).c_str(), file.ext.c_str()) == 0) - { - found = true; - break; - } - } - - if (!found) - { - continue; - } - } - } - else if (extensions.size() > 0) - { - continue; - } - } - - if (file.isFolder) - { - ++folderCount; - file.size = 0; - } - else - { - ++fileCount; - file.size = ((UINT64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow; - file.createdTime = fd.ftCreationTime; - file.modifiedTime = fd.ftLastWriteTime; - file.accessedTime = fd.ftLastAccessTime; - } - - file.sortAscending = sortAscending; // Used in sort functions - folderSize += file.size; - - files.push_back(file); - } - while (FindNextFile(find, &fd)); - FindClose(find); - - // Sort - auto begin = showDotDot ? files.begin() + 1: files.begin(); - switch (sortType) - { - case STYPE_NAME: - std::sort(begin, files.end(), SortByName); - break; - - case STYPE_SIZE: - std::sort(begin, files.end(), SortBySize); - break; - - case STYPE_TYPE: - std::sort(begin, files.end(), SortByExtension); - break; - - case STYPE_DATE: - switch (sortDateType) - { - case DTYPE_MODIFIED: - std::sort(begin, files.end(), SortByModifiedTime); - break; - - case DTYPE_CREATED: - std::sort(begin, files.end(), SortByCreatedTime); - break; - - case DTYPE_ACCESSED: - std::sort(begin, files.end(), SortByAccessedTime); - break; - } - break; - } - - if (isRecursive) - { - GetSubFolderSize(files, parentPath, folderCount, fileCount, folderSize); - } } } + + // Sort + const int sortAsc = tmp->sortAscending ? 1 : -1; + auto begin = ((tmp->path != L"" || !tmp->path.empty()) && (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL)) ? + tmp->files.begin() + 1: tmp->files.begin(); + + switch (tmp->sortType) + { + case STYPE_NAME: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + return file1.isFolder; + }); + break; + + case STYPE_SIZE: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc > 0) ? (file1.size < file2.size) : (file1.size > file2.size); + } + return file1.isFolder; + }); + break; + + case STYPE_TYPE: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + int result = (file1.ext.empty() && file2.ext.empty()) ? 0 : sortAsc * _wcsicmp(file1.ext.c_str(), file2.ext.c_str()); + return (0 != result) ? (result < 0) : (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + return file1.isFolder; + }); + break; + + case STYPE_DATE: + switch (tmp->sortDateType) + { + case DTYPE_MODIFIED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); + } + return file1.isFolder; + }); + break; + + case DTYPE_CREATED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); + } + return file1.isFolder; + }); + break; + + case DTYPE_ACCESSED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); + } + return file1.isFolder; + }); + break; + } + break; + } + + EnterCriticalSection(&g_CriticalSection); + parent->files.reserve(tmp->files.size()); + parent->files = tmp->files; + parent->fileCount = tmp->fileCount; + parent->folderCount = tmp->folderCount; + parent->folderSize = tmp->folderSize; + LeaveCriticalSection(&g_CriticalSection); } - if (needsIcons) + if (tmp->needsIcons) { - for (auto iter = children.begin(); iter != children.end(); ++iter) + for (auto iter : tmp->iconChildren) { EnterCriticalSection(&g_CriticalSection); - int trueIndex = (*iter)->ignoreCount ? (*iter)->index : (((*iter)->index % (*iter)->parent->count) + (*iter)->parent->indexOffset); - - if ((*iter)->type == TYPE_ICON && trueIndex >= 0 && trueIndex < files.size()) + int trueIndex = iter->ignoreCount ? iter->index : ((iter->index % iter->parent->count) + iter->parent->indexOffset); + + if (iter->type == TYPE_ICON && trueIndex >= 0 && trueIndex < tmp->files.size()) { - std::wstring filePath = parentPath; - filePath += (files[trueIndex].fileName == L"..") ? L"" : files[trueIndex].fileName; - GetIcon(filePath, (*iter)->iconPath, (*iter)->iconSize); + std::wstring filePath = tmp->files[trueIndex].path; + filePath += (tmp->files[trueIndex].fileName == L"..") ? L"" :tmp->files[trueIndex].fileName; + GetIcon(filePath, iter->iconPath, iter->iconSize); } - else if ((*iter)->type == TYPE_ICON) + else if (iter->type == TYPE_ICON) { - GetIcon(INVALID_FILE, (*iter)->iconPath, (*iter)->iconSize); + GetIcon(INVALID_FILE, iter->iconPath, iter->iconSize); } LeaveCriticalSection(&g_CriticalSection); } } EnterCriticalSection(&g_CriticalSection); - parent->files = files; - parent->fileCount = fileCount; - parent->folderCount = folderCount; - parent->folderSize = folderSize; - CloseHandle(parent->thread); - parent->thread = NULL; + parent->thread = nullptr; LeaveCriticalSection(&g_CriticalSection); - if (!parent->finishAction.empty()) + if (!tmp->finishAction.empty()) { - RmExecute(parent->skin, parent->finishAction.c_str()); + RmExecute(tmp->skin, tmp->finishAction.c_str()); } - _endthreadex(0); + delete tmp; return 0; } -void GetSubFolderSize(const std::vector files, const std::wstring path, int& folderCount, int& fileCount, UINT64& folderSize) +void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType) { - std::list folderQueue; - std::wstring folder; + std::wstring path = folder; + folder += (rType == RECURSIVE_PARTIAL) ? L"*" : parent->wildcardSearch; - // Get current folders first (if any) - for (auto iter = files.begin(); iter != files.end(); ++iter) + WIN32_FIND_DATA fd; + HANDLE find = FindFirstFileEx(folder.c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0); + + if (find != INVALID_HANDLE_VALUE) { - if ((*iter).isFolder && _wcsicmp((*iter).fileName.c_str(), L"..") != 0) + do { - folderQueue.push_back(path + (*iter).fileName); - } - } + FileInfo file; - while (!folderQueue.empty()) - { - std::list::reference ref = folderQueue.front(); - folder = ref + L"\\*"; - - WIN32_FIND_DATA fd; - HANDLE find = FindFirstFileEx(folder.c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, 0); - - if (find != INVALID_HANDLE_VALUE) - { - do + file.fileName = fd.cFileName; + if (_wcsicmp(file.fileName.c_str(), L".") == 0 || _wcsicmp(file.fileName.c_str(), L"..") == 0) { - folder = fd.cFileName; + continue; + } - if (_wcsicmp(folder.c_str(), L".") == 0 || _wcsicmp(folder.c_str(), L"..") == 0) + file.isFolder = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; + bool isHidden = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) > 0; + bool isSystem = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) > 0; + + if ((rType != RECURSIVE_PARTIAL) && + ((rType != RECURSIVE_FULL && !parent->showFile && !file.isFolder) || + (rType != RECURSIVE_FULL && !parent->showFolder && file.isFolder) || + (!parent->showHidden && isHidden) ||(!parent->showSystem && isSystem))) + { + continue; + } + + if (rType != RECURSIVE_PARTIAL && !file.isFolder) + { + size_t pos = file.fileName.find_last_of(L"."); + if (pos != std::wstring::npos) + { + file.ext = file.fileName.substr(pos + 1); + + if (parent->extensions.size() > 0) + { + bool found = false; + for (auto iter : parent->extensions) + { + if (_wcsicmp(iter.c_str(), file.ext.c_str()) == 0) + { + found = true; + break; + } + } + + if (!found) + { + continue; + } + } + } + else if (parent->extensions.size() > 0) { continue; } - - if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0) - { - ++folderCount; - folderQueue.push_back(ref + L"\\" + folder); - } - else - { - ++fileCount; - folderSize += ((UINT64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow; - } } - while (FindNextFile(find, &fd)); - - FindClose(find); + + if (file.isFolder) + { + if (rType != RECURSIVE_FULL) + { + ++parent->folderCount; + } + + folderQueue.push(path + file.fileName + L"\\"); + } + else + { + ++parent->fileCount; + file.size = ((UINT64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow; + } + + parent->folderSize += file.size; + + file.createdTime = fd.ftCreationTime; + file.modifiedTime = fd.ftLastWriteTime; + file.accessedTime = fd.ftLastAccessTime; + + file.path = path; + + if (rType == RECURSIVE_NONE || (rType == RECURSIVE_FULL && !file.isFolder)) + { + parent->files.push_back(file); + } } - - folderQueue.pop_front(); + while (FindNextFile(find, &fd)); + FindClose(find); } } void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize) { SHFILEINFO shFileInfo; - HICON icon = NULL; - HIMAGELIST* hImageList = NULL; - FILE* fp = NULL; + HICON icon = nullptr; + HIMAGELIST* hImageList = nullptr; + FILE* fp = nullptr; // Special case for .url files if (filePath.size() > 3 && _wcsicmp(filePath.substr(filePath.size() - 4).c_str(), L".URL") == 0) @@ -973,7 +1021,7 @@ void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize) case IS_MEDIUM: size = 32; break; } - PrivateExtractIcons(file.c_str(), iconIndex, size, size, &icon, NULL, 1, LR_LOADTRANSPARENT); + PrivateExtractIcons(file.c_str(), iconIndex, size, size, &icon, nullptr, 1, LR_LOADTRANSPARENT); } else { @@ -983,7 +1031,7 @@ void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize) HKEY hKey; RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command", 0, KEY_QUERY_VALUE, &hKey); - RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)buffer, &size); + RegQueryValueEx(hKey, nullptr, nullptr, nullptr, (LPBYTE)buffer, &size); RegCloseKey(hKey); //Strip quotes @@ -997,8 +1045,8 @@ void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize) filePath = browser; } } - - if (icon == NULL) + + if (icon == nullptr) { SHGetFileInfo(filePath.c_str(), 0, &shFileInfo, sizeof(shFileInfo), SHGFI_SYSICONINDEX); SHGetImageList(iconSize, IID_IImageList, (void**) &hImageList); @@ -1006,7 +1054,7 @@ void GetIcon(std::wstring filePath, std::wstring iconPath, IconSize iconSize) } errno_t error = _wfopen_s(&fp, iconPath.c_str(), L"wb"); - if (filePath == INVALID_FILE || icon == NULL || (error == 0 && !SaveIcon(icon, fp))) + if (filePath == INVALID_FILE || icon == nullptr || (error == 0 && !SaveIcon(icon, fp))) { fwrite(iconPath.c_str(), 1, 1, fp); // Clears previous icon fclose(fp); @@ -1020,7 +1068,7 @@ HRESULT SaveIcon(HICON hIcon, FILE* fp) ICONINFO iconInfo; BITMAP bmColor; BITMAP bmMask; - if (!fp || NULL == hIcon || !GetIconInfo(hIcon, &iconInfo) || + if (!fp || nullptr == hIcon || !GetIconInfo(hIcon, &iconInfo) || !GetObject(iconInfo.hbmColor, sizeof(bmColor), &bmColor) || !GetObject(iconInfo.hbmMask, sizeof(bmMask), &bmMask)) return false; @@ -1029,14 +1077,14 @@ HRESULT SaveIcon(HICON hIcon, FILE* fp) if (bmColor.bmBitsPixel != 16 && bmColor.bmBitsPixel != 32) return false; - HDC dc = GetDC(NULL); + HDC dc = GetDC(nullptr); BYTE bmiBytes[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; BITMAPINFO* bmi = (BITMAPINFO*)bmiBytes; // color bits memset(bmi, 0, sizeof(BITMAPINFO)); bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, NULL, bmi, DIB_RGB_COLORS); + GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, nullptr, bmi, DIB_RGB_COLORS); int colorBytesCount = bmi->bmiHeader.biSizeImage; BYTE* colorBits = new BYTE[colorBytesCount]; GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, colorBits, bmi, DIB_RGB_COLORS); @@ -1044,12 +1092,12 @@ HRESULT SaveIcon(HICON hIcon, FILE* fp) // mask bits memset(bmi, 0, sizeof(BITMAPINFO)); bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, NULL, bmi, DIB_RGB_COLORS); + GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, nullptr, bmi, DIB_RGB_COLORS); int maskBytesCount = bmi->bmiHeader.biSizeImage; BYTE* maskBits = new BYTE[maskBytesCount]; GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, maskBits, bmi, DIB_RGB_COLORS); - ReleaseDC(NULL, dc); + ReleaseDC(nullptr, dc); // icon data BITMAPINFOHEADER bmihIcon; diff --git a/Plugins/PluginFileView/PluginFileView.h b/Plugins/PluginFileView/PluginFileView.h index 1db155f5..627850b3 100644 --- a/Plugins/PluginFileView/PluginFileView.h +++ b/Plugins/PluginFileView/PluginFileView.h @@ -20,19 +20,16 @@ enum MeasureType { - TYPE_FOLDERPATH, // Current folder complete path - TYPE_FOLDERSIZE, // Current folder size - - TYPE_FILECOUNT, // Number of files of current folder - TYPE_FOLDERCOUNT, // Number of sub-folders under the current folder - - TYPE_FILENAME, // Name of file - TYPE_FILETYPE, // Type of file (ie "Text Document", not .txt) - TYPE_FILESIZE, // Size of file - TYPE_FILEDATE, // Date of file - Can be "Created Date", "Modified Date" etc. - TYPE_FILEPATH, // Full path of the file - - TYPE_ICON // Icon of file + TYPE_FOLDERPATH, + TYPE_FOLDERSIZE, + TYPE_FILECOUNT, + TYPE_FOLDERCOUNT, + TYPE_FILENAME, + TYPE_FILETYPE, + TYPE_FILESIZE, + TYPE_FILEDATE, + TYPE_FILEPATH, + TYPE_ICON }; enum DateType @@ -58,51 +55,45 @@ enum IconSize IS_EXLARGE = 4 // 256x256 }; +enum RecursiveType +{ + RECURSIVE_NONE, + RECURSIVE_PARTIAL, + RECURSIVE_FULL +}; + struct FileInfo { std::wstring fileName; - std::wstring typeName; // File type description + std::wstring path; std::wstring ext; bool isFolder; - bool sortAscending; // Used for sorting function (since we cannot pass other values to a sort function) UINT64 size; FILETIME createdTime; FILETIME modifiedTime; FILETIME accessedTime; - FileInfo(): sortAscending(false) - { - Clear(); - } - - void Clear() - { - fileName = L""; - typeName = L""; - ext = L""; - isFolder = false; - size = 0; - - createdTime.dwLowDateTime = 0; - createdTime.dwHighDateTime = 0; - modifiedTime.dwLowDateTime = 0; - modifiedTime.dwHighDateTime = 0; - accessedTime.dwLowDateTime = 0; - accessedTime.dwHighDateTime = 0; - } + FileInfo() : + fileName(L""), + path(L""), + ext(L""), + isFolder(false), + size(0), + createdTime(), + modifiedTime(), + accessedTime() { } }; struct ChildMeasure; struct ParentMeasure { - // Options from the .ini std::wstring path; std::wstring wildcardSearch; SortType sortType; DateType sortDateType; int count; - bool isRecursive; + RecursiveType recursiveType; bool sortAscending; bool showDotDot; bool showFile; @@ -110,11 +101,10 @@ struct ParentMeasure bool showHidden; bool showSystem; bool hideExtension; - std::vector extensions; // only show these extensions + std::vector extensions; std::wstring finishAction; - // Internal values - std::vector children; + std::vector iconChildren; std::vector files; int fileCount; int folderCount; @@ -124,7 +114,6 @@ struct ParentMeasure int indexOffset; HANDLE thread; - // References and identifying values void* skin; LPCWSTR name; ChildMeasure* ownerChild; @@ -145,23 +134,22 @@ struct ParentMeasure hideExtension(false), extensions(), finishAction(), - children(NULL), - files(NULL), - skin(NULL), + iconChildren(), + files(), + skin(nullptr), name(L""), - ownerChild(NULL), - thread(NULL), + ownerChild(nullptr), + thread(nullptr), fileCount(0), folderCount(0), needsUpdating(true), needsIcons(true), indexOffset(0), - isRecursive(false) { } + recursiveType(RECURSIVE_NONE) { } }; struct ChildMeasure { - // Options from the .ini MeasureType type; DateType date; IconSize iconSize; @@ -170,11 +158,7 @@ struct ChildMeasure bool ignoreCount; bool needsIcon; - // Internal values - double value; // numerical value of the value (if available) - std::wstring strValue; // string value of the value - - // References + std::wstring strValue; ParentMeasure* parent; ChildMeasure() : @@ -185,125 +169,27 @@ struct ChildMeasure index(1), ignoreCount(false), needsIcon(true), - value(0.0), - strValue(), - parent(NULL) { } + strValue(L""), + parent(nullptr) { } }; std::vector Tokenize(const std::wstring& str, const std::wstring& delimiters) { std::vector tokens; - std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); // skip delimiters at beginning. - std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); // find first "non-delimiter". + std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); + std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); while (std::wstring::npos != pos || std::wstring::npos != lastPos) { - tokens.push_back(str.substr(lastPos, pos - lastPos)); // found a token, add it to the vector. - lastPos = str.find_first_not_of(delimiters, pos); // skip delimiters. Note the "not_of" - pos = str.find_first_of(delimiters, lastPos); // find next "non-delimiter" + tokens.emplace_back(str.substr(lastPos, pos - lastPos)); + lastPos = str.find_first_not_of(delimiters, pos); + pos = str.find_first_of(delimiters, lastPos); } return tokens; } -bool SortByName(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sort * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - - return file1.isFolder; -} - -bool SortByExtension(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - int result = (file1.ext.empty() && file2.ext.empty()) ? 0 : sort * _wcsicmp(file1.ext.c_str(), file2.ext.c_str()); - return (0 != result) ? (result < 0) : (sort * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - - return file1.isFolder; -} - -bool SortBySize(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sort > 0) ? (file1.size < file2.size) : (file1.size > file2.size); - } - - return file1.isFolder; -} - -bool SortByAccessedTime(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sort * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); - } - - return file1.isFolder; -} - -bool SortByCreatedTime(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sort * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); - } - - return file1.isFolder; -} - -bool SortByModifiedTime(const FileInfo& file1, const FileInfo& file2) -{ - int sort = file1.sortAscending ? 1 : -1; - - if (file1.isFolder && file2.isFolder) - { - return (sort * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sort * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); - } - - return file1.isFolder; -} - /*std::wstring UINT64_To_String(UINT64 value) { std::wstring result; diff --git a/Plugins/PluginFileView/PluginFileView.rc b/Plugins/PluginFileView/PluginFileView.rc index 3b974d21..7a8759f2 100644 --- a/Plugins/PluginFileView/PluginFileView.rc +++ b/Plugins/PluginFileView/PluginFileView.rc @@ -7,7 +7,7 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 + FILEVERSION 2,0,0,0 PRODUCTVERSION PRODUCTVER FILEFLAGSMASK 0x17L #ifdef _DEBUG @@ -23,7 +23,7 @@ VS_VERSION_INFO VERSIONINFO { BLOCK "040904E4" { - VALUE "FileVersion", "1.2.0.0" + VALUE "FileVersion", "2.0.0.0" VALUE "LegalCopyright", "© 2012 - Brian Ferguson" VALUE "ProductName", "Rainmeter" #ifdef _WIN64 diff --git a/Plugins/PluginFileView/StdAfx.h b/Plugins/PluginFileView/StdAfx.h index 2d27ab44..ef133e4d 100644 --- a/Plugins/PluginFileView/StdAfx.h +++ b/Plugins/PluginFileView/StdAfx.h @@ -28,7 +28,7 @@ // STL #include #include -#include +#include #include // Rainmeter API