mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-27 07:44:24 +02:00
File Browser (in progress)
Make file and folder add/delete/rename detection from outside work.
This commit is contained in:
parent
a1c608ba61
commit
0ad1964d1d
@ -580,7 +580,7 @@ POINT FileBrowser::getMenuDisplayPoint(int iButton)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTREEITEM FileBrowser::addFolder(HTREEITEM hTreeItem, const TCHAR *folderName)
|
HTREEITEM FileBrowser::createNewFolder(HTREEITEM hTreeItem, const TCHAR *folderName)
|
||||||
{
|
{
|
||||||
HTREEITEM addedItem = _treeView.addItem(folderName, hTreeItem, INDEX_CLOSED_NODE);
|
HTREEITEM addedItem = _treeView.addItem(folderName, hTreeItem, INDEX_CLOSED_NODE);
|
||||||
|
|
||||||
@ -634,12 +634,12 @@ void FileBrowser::popupMenuCmd(int cmdID)
|
|||||||
case IDM_FILEBROWSER_RENAME :
|
case IDM_FILEBROWSER_RENAME :
|
||||||
TreeView_EditLabel(_treeView.getHSelf(), hTreeItem);
|
TreeView_EditLabel(_treeView.getHSelf(), hTreeItem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDM_FILEBROWSER_NEWFOLDER :
|
case IDM_FILEBROWSER_NEWFOLDER :
|
||||||
{
|
{
|
||||||
NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance())->getNativeLangSpeaker();
|
NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance())->getNativeLangSpeaker();
|
||||||
generic_string newFolderLabel = pNativeSpeaker->getAttrNameStr(PM_NEWFOLDERNAME, "ProjectManager", "NewFolderName");
|
generic_string newFolderLabel = pNativeSpeaker->getAttrNameStr(PM_NEWFOLDERNAME, "ProjectManager", "NewFolderName");
|
||||||
addFolder(hTreeItem, newFolderLabel.c_str());
|
createNewFolder(hTreeItem, newFolderLabel.c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -654,7 +654,8 @@ void FileBrowser::popupMenuCmd(int cmdID)
|
|||||||
_treeView.moveUp(hTreeItem);
|
_treeView.moveUp(hTreeItem);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
case IDM_FILEBROWSER_ADDFILES :
|
case IDM_FILEBROWSER_ADDFILES :
|
||||||
{
|
{
|
||||||
addFiles(hTreeItem);
|
addFiles(hTreeItem);
|
||||||
@ -662,6 +663,7 @@ void FileBrowser::popupMenuCmd(int cmdID)
|
|||||||
_treeView.setItemImage(hTreeItem, INDEX_OPEN_NODE, INDEX_OPEN_NODE);
|
_treeView.setItemImage(hTreeItem, INDEX_OPEN_NODE, INDEX_OPEN_NODE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
case IDM_FILEBROWSER_DELETEFOLDER :
|
case IDM_FILEBROWSER_DELETEFOLDER :
|
||||||
{
|
{
|
||||||
@ -701,84 +703,12 @@ void FileBrowser::popupMenuCmd(int cmdID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::addFiles(HTREEITEM hTreeItem)
|
|
||||||
{
|
|
||||||
FileDialog fDlg(_hSelf, ::GetModuleHandle(NULL));
|
|
||||||
fDlg.setExtFilter(TEXT("All types"), TEXT(".*"), NULL);
|
|
||||||
|
|
||||||
if (stringVector *pfns = fDlg.doOpenMultiFilesDlg())
|
|
||||||
{
|
|
||||||
size_t sz = pfns->size();
|
|
||||||
for (size_t i = 0 ; i < sz ; ++i)
|
|
||||||
{
|
|
||||||
TCHAR *strValueLabel = ::PathFindFileName(pfns->at(i).c_str());
|
|
||||||
_treeView.addItem(strValueLabel, hTreeItem, INDEX_LEAF, pfns->at(i).c_str());
|
|
||||||
}
|
|
||||||
_treeView.expand(hTreeItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBrowser::recursiveAddFilesFrom(const TCHAR *folderPath, HTREEITEM hTreeItem)
|
|
||||||
{
|
|
||||||
bool isRecursive = true;
|
|
||||||
bool isInHiddenDir = false;
|
|
||||||
generic_string dirFilter(folderPath);
|
|
||||||
if (folderPath[lstrlen(folderPath)-1] != '\\')
|
|
||||||
dirFilter += TEXT("\\");
|
|
||||||
|
|
||||||
dirFilter += TEXT("*.*");
|
|
||||||
WIN32_FIND_DATA foundData;
|
|
||||||
std::vector<generic_string> files;
|
|
||||||
|
|
||||||
HANDLE hFile = ::FindFirstFile(dirFilter.c_str(), &foundData);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
{
|
|
||||||
if (!isInHiddenDir && (foundData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
else if (isRecursive)
|
|
||||||
{
|
|
||||||
if ((lstrcmp(foundData.cFileName, TEXT("."))) && (lstrcmp(foundData.cFileName, TEXT(".."))))
|
|
||||||
{
|
|
||||||
generic_string pathDir(folderPath);
|
|
||||||
if (folderPath[lstrlen(folderPath)-1] != '\\')
|
|
||||||
pathDir += TEXT("\\");
|
|
||||||
pathDir += foundData.cFileName;
|
|
||||||
pathDir += TEXT("\\");
|
|
||||||
HTREEITEM addedItem = addFolder(hTreeItem, foundData.cFileName);
|
|
||||||
recursiveAddFilesFrom(pathDir.c_str(), addedItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
files.push_back(foundData.cFileName);
|
|
||||||
}
|
|
||||||
} while (::FindNextFile(hFile, &foundData));
|
|
||||||
|
|
||||||
for (size_t i = 0, len = files.size() ; i < len ; ++i)
|
|
||||||
{
|
|
||||||
generic_string pathFile(folderPath);
|
|
||||||
if (folderPath[lstrlen(folderPath)-1] != '\\')
|
|
||||||
pathFile += TEXT("\\");
|
|
||||||
pathFile += files[i];
|
|
||||||
_treeView.addItem(files[i].c_str(), hTreeItem, INDEX_LEAF, pathFile.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
::FindClose(hFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir)
|
void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir)
|
||||||
{
|
{
|
||||||
directoryStructure.setPath(dir);
|
if (directoryStructure._parent == nullptr) // Root!
|
||||||
|
directoryStructure.setRootPath(dir);
|
||||||
|
|
||||||
generic_string dirFilter(dir);
|
generic_string dirFilter(dir);
|
||||||
dirFilter += TEXT("*.*");
|
dirFilter += TEXT("*.*");
|
||||||
@ -803,7 +733,7 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
|
|||||||
pathDir += foundData.cFileName;
|
pathDir += foundData.cFileName;
|
||||||
pathDir += TEXT("\\");
|
pathDir += TEXT("\\");
|
||||||
|
|
||||||
FolderInfo subDirectoryStructure;
|
FolderInfo subDirectoryStructure(foundData.cFileName, &directoryStructure);
|
||||||
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
|
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
|
||||||
directoryStructure.addSubFolder(subDirectoryStructure);
|
directoryStructure.addSubFolder(subDirectoryStructure);
|
||||||
}
|
}
|
||||||
@ -813,12 +743,11 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
|
|||||||
{
|
{
|
||||||
if (matchInList(foundData.cFileName, patterns))
|
if (matchInList(foundData.cFileName, patterns))
|
||||||
{
|
{
|
||||||
generic_string pathFile(dir);
|
directoryStructure.addFile(foundData.cFileName);
|
||||||
pathFile += foundData.cFileName;
|
|
||||||
directoryStructure.addFile(pathFile.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (::FindNextFile(hFile, &foundData))
|
while (::FindNextFile(hFile, &foundData))
|
||||||
{
|
{
|
||||||
if (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
@ -835,7 +764,7 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
|
|||||||
pathDir += foundData.cFileName;
|
pathDir += foundData.cFileName;
|
||||||
pathDir += TEXT("\\");
|
pathDir += TEXT("\\");
|
||||||
|
|
||||||
FolderInfo subDirectoryStructure;
|
FolderInfo subDirectoryStructure(foundData.cFileName, &directoryStructure);
|
||||||
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
|
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
|
||||||
directoryStructure.addSubFolder(subDirectoryStructure);
|
directoryStructure.addSubFolder(subDirectoryStructure);
|
||||||
}
|
}
|
||||||
@ -845,9 +774,7 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
|
|||||||
{
|
{
|
||||||
if (matchInList(foundData.cFileName, patterns))
|
if (matchInList(foundData.cFileName, patterns))
|
||||||
{
|
{
|
||||||
generic_string pathFile(dir);
|
directoryStructure.addFile(foundData.cFileName);
|
||||||
pathFile += foundData.cFileName;
|
|
||||||
directoryStructure.addFile(pathFile.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -856,40 +783,40 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
|
|||||||
|
|
||||||
void FileBrowser::addRootFolder(generic_string rootFolderPath)
|
void FileBrowser::addRootFolder(generic_string rootFolderPath)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < _folderUpdaters.size(); ++i)
|
size_t nbFolderUpdaters = _folderUpdaters.size();
|
||||||
|
for (size_t i = 0; i < nbFolderUpdaters; ++i)
|
||||||
{
|
{
|
||||||
if (_folderUpdaters[i]._rootFolder._path == rootFolderPath)
|
if (_folderUpdaters[i]._rootFolder._rootPath == rootFolderPath)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<generic_string> patterns2Match;
|
std::vector<generic_string> patterns2Match;
|
||||||
patterns2Match.push_back(TEXT("*.*"));
|
patterns2Match.push_back(TEXT("*.*"));
|
||||||
|
|
||||||
FolderInfo directoryStructure;
|
TCHAR *label = ::PathFindFileName(rootFolderPath.c_str());
|
||||||
|
FolderInfo directoryStructure(label, nullptr);
|
||||||
getDirectoryStructure(rootFolderPath.c_str(), patterns2Match, directoryStructure, true, false);
|
getDirectoryStructure(rootFolderPath.c_str(), patterns2Match, directoryStructure, true, false);
|
||||||
HTREEITEM hRootItem = createFolderItemsFromDirStruct(nullptr, directoryStructure);
|
HTREEITEM hRootItem = createFolderItemsFromDirStruct(nullptr, directoryStructure);
|
||||||
_treeView.expand(hRootItem);
|
_treeView.expand(hRootItem);
|
||||||
_folderUpdaters.push_back(FolderUpdater(directoryStructure, _hSelf));
|
_folderUpdaters.push_back(FolderUpdater(directoryStructure, this));
|
||||||
_folderUpdaters[_folderUpdaters.size() - 1].startWatcher();
|
_folderUpdaters[_folderUpdaters.size() - 1].startWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, const FolderInfo & directoryStructure)
|
HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, const FolderInfo & directoryStructure)
|
||||||
{
|
{
|
||||||
TCHAR rootPath[MAX_PATH];
|
|
||||||
lstrcpy(rootPath, directoryStructure._path.c_str());
|
|
||||||
size_t len = lstrlen(rootPath);
|
|
||||||
if (rootPath[len-1] == '\\')
|
|
||||||
rootPath[len-1] = '\0';
|
|
||||||
|
|
||||||
TCHAR *rootName = ::PathFindFileName(rootPath);
|
|
||||||
HTREEITEM hFolderItem = nullptr;
|
HTREEITEM hFolderItem = nullptr;
|
||||||
if (hParentItem == nullptr)
|
if (directoryStructure._parent == nullptr && hParentItem == nullptr)
|
||||||
{
|
{
|
||||||
hFolderItem = _treeView.addItem(rootName, TVI_ROOT, INDEX_CLOSED_NODE);
|
TCHAR rootPath[MAX_PATH];
|
||||||
|
lstrcpy(rootPath, directoryStructure._rootPath.c_str());
|
||||||
|
size_t len = lstrlen(rootPath);
|
||||||
|
if (rootPath[len - 1] == '\\')
|
||||||
|
rootPath[len - 1] = '\0';
|
||||||
|
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), TVI_ROOT, INDEX_CLOSED_NODE, rootPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hFolderItem = addFolder(hParentItem, rootName);
|
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), hParentItem, INDEX_CLOSED_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < directoryStructure._subFolders.size(); ++i)
|
for (size_t i = 0; i < directoryStructure._subFolders.size(); ++i)
|
||||||
@ -899,218 +826,328 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
|
|||||||
|
|
||||||
for (size_t i = 0; i < directoryStructure._files.size(); ++i)
|
for (size_t i = 0; i < directoryStructure._files.size(); ++i)
|
||||||
{
|
{
|
||||||
TCHAR filePath[MAX_PATH];
|
_treeView.addItem(directoryStructure._files[i]._name.c_str(), hFolderItem, INDEX_LEAF);
|
||||||
lstrcpy(filePath, directoryStructure._files[i]._path.c_str());
|
|
||||||
TCHAR *fileName = ::PathFindFileName(filePath);
|
|
||||||
_treeView.addItem(fileName, hFolderItem, INDEX_LEAF, directoryStructure._files[i]._path.c_str());
|
|
||||||
}
|
}
|
||||||
_treeView.fold(hParentItem);
|
_treeView.fold(hParentItem);
|
||||||
|
|
||||||
return hFolderItem;
|
return hFolderItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FolderInfo::compare(const FolderInfo & struct2compare, std::vector<changeInfo> & result)
|
HTREEITEM FileBrowser::getRootFromFullPath(generic_string rootPath)
|
||||||
{
|
{
|
||||||
if (_contentHash == struct2compare._contentHash)
|
HTREEITEM node = nullptr;
|
||||||
|
for (HTREEITEM hItemNode = _treeView.getRoot();
|
||||||
|
hItemNode != nullptr && node == nullptr;
|
||||||
|
hItemNode = _treeView.getNextSibling(hItemNode))
|
||||||
{
|
{
|
||||||
if (_path == struct2compare._path) // Everything is fine
|
TVITEM tvItem;
|
||||||
|
tvItem.mask = TVIF_PARAM;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
tvItem.hItem = hItemNode;
|
||||||
|
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
|
||||||
|
if (tvItem.lParam != 0 && rootPath == *((generic_string *)tvItem.lParam))
|
||||||
|
node = hItemNode;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, generic_string label)
|
||||||
|
{
|
||||||
|
HTREEITEM childNodeFound = nullptr;
|
||||||
|
|
||||||
|
for (HTREEITEM hItemNode = _treeView.getChildFrom(parent);
|
||||||
|
hItemNode != NULL && childNodeFound == nullptr;
|
||||||
|
hItemNode = _treeView.getNextSibling(hItemNode))
|
||||||
|
{
|
||||||
|
TCHAR textBuffer[MAX_PATH];
|
||||||
|
TVITEM tvItem;
|
||||||
|
tvItem.mask = TVIF_TEXT;
|
||||||
|
tvItem.pszText = textBuffer;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
tvItem.hItem = hItemNode;
|
||||||
|
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
|
||||||
|
if (label == tvItem.pszText)
|
||||||
{
|
{
|
||||||
return true;
|
childNodeFound = hItemNode;
|
||||||
}
|
|
||||||
else // folder is renamed
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.rename;
|
|
||||||
info._fullFilePath = struct2compare._path;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // sub-folders or files/sub-files deleted or renamed
|
return childNodeFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBrowser::addInTree(generic_string rootPath, generic_string addItemFullPath, HTREEITEM node, vector<generic_string> linarPathArray)
|
||||||
|
{
|
||||||
|
if (node == nullptr) // it's a root. Search the right root with rootPath
|
||||||
{
|
{
|
||||||
if (_path != struct2compare._path) // both content and path are different, stop to compare
|
// Search
|
||||||
{
|
if ((node = getRootFromFullPath(rootPath)) == nullptr)
|
||||||
return true; // everything could be fine
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check folder (maybe go deeper)
|
if (linarPathArray.size() == 1)
|
||||||
for (size_t i = 0; i < _subFolders.size(); ++i)
|
{
|
||||||
|
// Search : if no found, add
|
||||||
|
HTREEITEM childNodeFound = findChildNodeFromName(node, linarPathArray[0]);
|
||||||
|
if (childNodeFound != nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// No found, good - Action
|
||||||
|
if (::PathIsDirectory(addItemFullPath.c_str()))
|
||||||
{
|
{
|
||||||
bool isFound = false;
|
_treeView.addItem(linarPathArray[0].c_str(), node, INDEX_CLOSED_NODE);
|
||||||
for (size_t j = 0; j < struct2compare._subFolders.size(); ++j)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_treeView.addItem(linarPathArray[0].c_str(), node, INDEX_LEAF);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HTREEITEM childNodeFound = nullptr;
|
||||||
|
for (HTREEITEM hItemNode = _treeView.getChildFrom(node);
|
||||||
|
hItemNode != NULL && childNodeFound == nullptr;
|
||||||
|
hItemNode = _treeView.getNextSibling(hItemNode))
|
||||||
|
{
|
||||||
|
TCHAR textBuffer[MAX_PATH];
|
||||||
|
TVITEM tvItem;
|
||||||
|
tvItem.mask = TVIF_TEXT;
|
||||||
|
tvItem.pszText = textBuffer;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
tvItem.hItem = hItemNode;
|
||||||
|
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
|
||||||
|
if (linarPathArray[0] == tvItem.pszText)
|
||||||
{
|
{
|
||||||
if ((_subFolders[i]._path == struct2compare._subFolders[j]._path) &&
|
// search recursively the node for an action
|
||||||
(_subFolders[i]._contentHash == struct2compare._subFolders[j]._contentHash))
|
linarPathArray.erase(linarPathArray.begin());
|
||||||
{
|
return addInTree(rootPath, addItemFullPath, hItemNode, linarPathArray);
|
||||||
isFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((_subFolders[i]._path != struct2compare._subFolders[j]._path) &&
|
|
||||||
(_subFolders[i]._contentHash == struct2compare._subFolders[j]._contentHash)) // rename
|
|
||||||
{
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.rename;
|
|
||||||
info._fullFilePath = struct2compare._path;
|
|
||||||
}
|
|
||||||
else if ((_subFolders[i]._path == struct2compare._subFolders[j]._path) &&
|
|
||||||
(_subFolders[i]._contentHash != struct2compare._subFolders[j]._contentHash)) // problem of sub-files or sub-folders. go deeper
|
|
||||||
{
|
|
||||||
_subFolders[i].compare(struct2compare._subFolders[j], result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (not isFound) // folder is deleted
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.remove;
|
|
||||||
info._fullFilePath = _subFolders[i]._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//check files
|
bool FileBrowser::deleteFromTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray)
|
||||||
|
{
|
||||||
|
if (node == nullptr) // it's a root. Search the right root with rootPath
|
||||||
|
{
|
||||||
|
// Search
|
||||||
|
if ((node = getRootFromFullPath(rootPath)) == nullptr)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linarPathArray.size() == 1)
|
||||||
|
{
|
||||||
|
// Search
|
||||||
|
HTREEITEM childNodeFound = findChildNodeFromName(node, linarPathArray[0]);
|
||||||
|
if (childNodeFound == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// found it, delete it
|
||||||
|
_treeView.removeItem(childNodeFound);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HTREEITEM childNodeFound = nullptr;
|
||||||
|
for (HTREEITEM hItemNode = _treeView.getChildFrom(node);
|
||||||
|
hItemNode != NULL && childNodeFound == nullptr;
|
||||||
|
hItemNode = _treeView.getNextSibling(hItemNode))
|
||||||
|
{
|
||||||
|
TCHAR textBuffer[MAX_PATH];
|
||||||
|
TVITEM tvItem;
|
||||||
|
tvItem.mask = TVIF_TEXT;
|
||||||
|
tvItem.pszText = textBuffer;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
tvItem.hItem = hItemNode;
|
||||||
|
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
|
||||||
|
if (linarPathArray[0] == tvItem.pszText)
|
||||||
|
{
|
||||||
|
// search recursively the node for an action
|
||||||
|
linarPathArray.erase(linarPathArray.begin());
|
||||||
|
return deleteFromTree(rootPath, hItemNode, linarPathArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBrowser::renameInTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo)
|
||||||
|
{
|
||||||
|
if (node == nullptr) // it's a root. Search the right root with rootPath
|
||||||
|
{
|
||||||
|
// Search
|
||||||
|
if ((node = getRootFromFullPath(rootPath)) == nullptr)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linarPathArrayFrom.size() == 1)
|
||||||
|
{
|
||||||
|
// Search
|
||||||
|
HTREEITEM childNodeFound = findChildNodeFromName(node, linarPathArrayFrom[0]);
|
||||||
|
if (childNodeFound == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// found it, rename it
|
||||||
|
_treeView.renameItem(childNodeFound, linarPathArrayTo[0].c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HTREEITEM childNodeFound = nullptr;
|
||||||
|
for (HTREEITEM hItemNode = _treeView.getChildFrom(node);
|
||||||
|
hItemNode != NULL && childNodeFound == nullptr;
|
||||||
|
hItemNode = _treeView.getNextSibling(hItemNode))
|
||||||
|
{
|
||||||
|
TCHAR textBuffer[MAX_PATH];
|
||||||
|
TVITEM tvItem;
|
||||||
|
tvItem.mask = TVIF_TEXT;
|
||||||
|
tvItem.pszText = textBuffer;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
tvItem.hItem = hItemNode;
|
||||||
|
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
|
||||||
|
if (linarPathArrayFrom[0] == tvItem.pszText)
|
||||||
|
{
|
||||||
|
// search recursively the node for an action
|
||||||
|
linarPathArrayFrom.erase(linarPathArrayFrom.begin());
|
||||||
|
linarPathArrayTo.erase(linarPathArrayTo.begin());
|
||||||
|
return renameInTree(rootPath, hItemNode, linarPathArrayFrom, linarPathArrayTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray)
|
||||||
|
{
|
||||||
|
if (linarPathArray.size() == 1) // could be file or folder
|
||||||
|
{
|
||||||
|
fullpath += TEXT("\\");
|
||||||
|
fullpath += linarPathArray[0];
|
||||||
|
if (PathIsDirectory(fullpath.c_str()))
|
||||||
|
{
|
||||||
|
// search in folders, if found - no good
|
||||||
|
size_t nbFolder = _subFolders.size();
|
||||||
|
for (size_t i = 0; i < nbFolder; ++i)
|
||||||
|
{
|
||||||
|
if (linarPathArray[0] == _subFolders[i].getName())
|
||||||
|
return false; // Maybe already added?
|
||||||
|
}
|
||||||
|
_subFolders.push_back(FolderInfo(linarPathArray[0], this));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// search in files, if found - no good
|
||||||
|
size_t nbFile = _files.size();
|
||||||
|
for (size_t i = 0; i < nbFile; ++i)
|
||||||
|
{
|
||||||
|
if (linarPathArray[0] == _files[i].getName())
|
||||||
|
return false; // Maybe already added?
|
||||||
|
}
|
||||||
|
_files.push_back(FileInfo(linarPathArray[0], this));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // folder
|
||||||
|
{
|
||||||
|
size_t nbFolder = _subFolders.size();
|
||||||
|
for (size_t i = 0; i < nbFolder; ++i)
|
||||||
|
{
|
||||||
|
if (_subFolders[i].getName() == linarPathArray[0])
|
||||||
|
{
|
||||||
|
fullpath += TEXT("\\");
|
||||||
|
fullpath += linarPathArray[0];
|
||||||
|
linarPathArray.erase(linarPathArray.begin());
|
||||||
|
return _subFolders[i].addToStructure(fullpath, linarPathArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
|
||||||
|
{
|
||||||
|
if (linarPathArray.size() == 1) // could be file or folder
|
||||||
|
{
|
||||||
for (size_t i = 0; i < _files.size(); ++i)
|
for (size_t i = 0; i < _files.size(); ++i)
|
||||||
{
|
{
|
||||||
bool isFound = false;
|
if (_files[i].getName() == linarPathArray[0])
|
||||||
for (size_t j = 0; not isFound && j < struct2compare._files.size(); ++j)
|
|
||||||
{
|
{
|
||||||
if (_files[i]._path == struct2compare._files[j]._path)
|
// remove this file
|
||||||
isFound = true;
|
_files.erase(_files.begin() + i);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
if (not isFound) // file is deleted
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.remove;
|
|
||||||
info._fullFilePath = _files[i]._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
for (size_t i = 0; i < struct2compare._files.size(); ++i)
|
for (size_t i = 0; i < _subFolders.size(); ++i)
|
||||||
{
|
{
|
||||||
bool isFound = false;
|
if (_subFolders[i].getName() == linarPathArray[0])
|
||||||
for (size_t j = 0; not isFound && j < _files.size(); ++j)
|
|
||||||
{
|
{
|
||||||
if (_files[i]._path == struct2compare._files[j]._path)
|
// remove this folder
|
||||||
isFound = true;
|
_subFolders.erase(_subFolders.begin() + i);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
if (not isFound) // file is deleted
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.add;
|
|
||||||
info._fullFilePath = struct2compare._files[i]._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else // folder
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < _subFolders.size(); ++i)
|
||||||
|
{
|
||||||
|
if (_subFolders[i].getName() == linarPathArray[0])
|
||||||
|
{
|
||||||
|
linarPathArray.erase(linarPathArray.begin());
|
||||||
|
return _subFolders[i].removeFromStructure(linarPathArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FolderInfo::makeDiff(FolderInfo & struct1, FolderInfo & struct2, std::vector<changeInfo> result)
|
bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo)
|
||||||
{
|
{
|
||||||
if (struct1._contentHash == struct2._contentHash)
|
if (linarPathArrayFrom.size() == 1) // could be file or folder
|
||||||
{
|
{
|
||||||
if (struct1._path == struct2._path) // Everything is fine
|
for (size_t i = 0; i < _files.size(); ++i)
|
||||||
{
|
{
|
||||||
// remove both
|
if (_files[i].getName() == linarPathArrayFrom[0])
|
||||||
return true;
|
{
|
||||||
|
// rename this file
|
||||||
|
_files[i].setName(linarPathArrayTo[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else // folder is renamed
|
|
||||||
|
for (size_t i = 0; i < _subFolders.size(); ++i)
|
||||||
{
|
{
|
||||||
// put result in the vector
|
if (_subFolders[i].getName() == linarPathArrayFrom[0])
|
||||||
changeInfo info;
|
{
|
||||||
info._action = info.rename;
|
// rename this folder
|
||||||
info._fullFilePath = struct2._path;
|
_subFolders[i].setName(linarPathArrayTo[0]);
|
||||||
result.push_back(info);
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else // sub-folders or files/sub-files deleted or renamed
|
else // folder
|
||||||
{
|
{
|
||||||
if (struct1._path != struct2._path) // both content and path are different, stop to compare
|
for (size_t i = 0; i < _subFolders.size(); ++i)
|
||||||
{
|
{
|
||||||
return true; // everything could be fine
|
if (_subFolders[i].getName() == linarPathArrayFrom[0])
|
||||||
}
|
|
||||||
|
|
||||||
//check folder (maybe go deeper)
|
|
||||||
for (int i = struct1._subFolders.size(); i >= 0; --i)
|
|
||||||
{
|
|
||||||
bool isFound = false;
|
|
||||||
for (int j = struct2._subFolders.size(); not isFound && j >= 0; --j)
|
|
||||||
{
|
{
|
||||||
if ((struct1._subFolders[i]._path == struct2._subFolders[j]._path) &&
|
linarPathArrayFrom.erase(linarPathArrayFrom.begin());
|
||||||
(struct1._subFolders[i]._contentHash == struct2._subFolders[j]._contentHash))
|
linarPathArrayTo.erase(linarPathArrayTo.begin());
|
||||||
{
|
return _subFolders[i].renameInStructure(linarPathArrayFrom, linarPathArrayTo);
|
||||||
struct1._subFolders.erase(struct1._subFolders.begin() + i);
|
|
||||||
struct2._subFolders.erase(struct2._subFolders.begin() + j);
|
|
||||||
isFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((struct1._subFolders[i]._path != struct2._subFolders[j]._path) &&
|
|
||||||
(struct1._subFolders[i]._contentHash == struct2._subFolders[j]._contentHash)) // rename
|
|
||||||
{
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.rename;
|
|
||||||
info._fullFilePath = struct2._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
|
||||||
else if ((struct1._subFolders[i]._path == struct2._subFolders[j]._path) &&
|
|
||||||
(struct1._subFolders[i]._contentHash != struct2._subFolders[j]._contentHash)) // problem of sub-files or sub-folders. go deeper
|
|
||||||
{
|
|
||||||
makeDiff(struct1._subFolders[i], struct2._subFolders[j], result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (not isFound) // folder is deleted
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.remove;
|
|
||||||
info._fullFilePath = struct1._subFolders[i]._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
//check files
|
|
||||||
for (int i = struct1._files.size(); i >= 0; --i)
|
|
||||||
{
|
|
||||||
bool isFound = false;
|
|
||||||
for (int j = struct2._files.size(); not isFound && j >= 0; --j)
|
|
||||||
{
|
|
||||||
if (struct1._files[i]._path == struct2._files[j]._path)
|
|
||||||
{
|
|
||||||
struct1._subFolders.erase(struct1._subFolders.begin() + i);
|
|
||||||
struct2._subFolders.erase(struct2._subFolders.begin() + j);
|
|
||||||
isFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not isFound) // file is deleted
|
|
||||||
{
|
|
||||||
// put result in the vector
|
|
||||||
changeInfo info;
|
|
||||||
info._action = info.remove;
|
|
||||||
info._fullFilePath = struct1._files[i]._path;
|
|
||||||
result.push_back(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generic_string FolderInfo::getLabel()
|
|
||||||
{
|
|
||||||
return ::PathFindFileName(_path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderUpdater::startWatcher()
|
void FolderUpdater::startWatcher()
|
||||||
{
|
{
|
||||||
// no thread yet, create a event with non-signaled, to block all threads
|
// no thread yet, create a event with non-signaled, to block all threads
|
||||||
@ -1144,45 +1181,113 @@ LPCWSTR explainAction(DWORD dwAction)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vector<generic_string> split(const generic_string & string2split, TCHAR sep)
|
||||||
|
{
|
||||||
|
vector<generic_string> splitedStrings;
|
||||||
|
size_t len = string2split.length();
|
||||||
|
size_t beginPos = 0;
|
||||||
|
for (size_t i = 0; i < len + 1; ++i)
|
||||||
|
{
|
||||||
|
if (string2split[i] == sep || string2split[i] == '\0')
|
||||||
|
{
|
||||||
|
splitedStrings.push_back(string2split.substr(beginPos, i - beginPos));
|
||||||
|
beginPos = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return splitedStrings;
|
||||||
|
};
|
||||||
|
|
||||||
bool FolderUpdater::updateTree(DWORD action, const std::vector<generic_string> & file2Change)
|
bool FolderUpdater::updateTree(DWORD action, const std::vector<generic_string> & file2Change)
|
||||||
{
|
{
|
||||||
//TCHAR msg2show[1024];
|
/*
|
||||||
|
TCHAR msg2show[1024];
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case FILE_ACTION_ADDED:
|
case FILE_ACTION_ADDED:
|
||||||
//swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
|
swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
|
||||||
//printStr(msg2show);
|
printStr(msg2show);
|
||||||
//::PostMessage(thisFolderUpdater->_hFileBrowser, FB_ADDFILE, nullptr, (LPARAM)wstrFilename.GetString());
|
//::PostMessage(thisFolderUpdater->_hFileBrowser, FB_ADDFILE, nullptr, (LPARAM)wstrFilename.GetString());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_ACTION_REMOVED:
|
case FILE_ACTION_REMOVED:
|
||||||
//swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
|
swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
|
||||||
//printStr(msg2show);
|
printStr(msg2show);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||||
//swprintf(msg2show, L"%s from %s \rto %s", explainAction(action), file2Change[0].c_str(), file2Change[1].c_str());
|
swprintf(msg2show, L"%s from %s \rto %s", explainAction(action), file2Change[0].c_str(), file2Change[1].c_str());
|
||||||
//printStr(msg2show);
|
printStr(msg2show);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
generic_string separator = TEXT("\\\\");
|
generic_string separator = TEXT("\\\\");
|
||||||
|
|
||||||
size_t sepPos = file2Change[0].find(separator);
|
size_t sepPos = file2Change[0].find(separator);
|
||||||
if (sepPos == generic_string::npos)
|
if (sepPos == generic_string::npos)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
generic_string rootPrefix = file2Change[0].substr(0, sepPos);
|
|
||||||
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
|
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
|
||||||
|
|
||||||
// found: remove prefix of file/folder in changeInfo, splite the remained path
|
// remove prefix of file/folder in changeInfo, splite the remained path
|
||||||
|
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
|
||||||
|
|
||||||
// search recursively according indication (file or folder)
|
if (action == FILE_ACTION_ADDED)
|
||||||
|
{
|
||||||
|
generic_string rootPath = file2Change[0].substr(0, sepPos);
|
||||||
|
generic_string path = rootPath;
|
||||||
|
// search recursively and modify the tree structure
|
||||||
|
bool foundAndModified = _rootFolder.addToStructure(path, linarPathArray);
|
||||||
|
if (foundAndModified)
|
||||||
|
{
|
||||||
|
generic_string addedFilePath = file2Change[0].substr(0, sepPos + 1);
|
||||||
|
addedFilePath += pathSuffix;
|
||||||
|
bool isAdded = _pFileBrowser->addInTree(rootPath, addedFilePath, nullptr, linarPathArray);
|
||||||
|
if (not isAdded)
|
||||||
|
MessageBox(NULL, addedFilePath.c_str(), TEXT("file/folder is not added"), MB_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printStr(TEXT("addToStructure pb"));
|
||||||
|
}
|
||||||
|
else if (action == FILE_ACTION_REMOVED)
|
||||||
|
{
|
||||||
|
generic_string rootPath = file2Change[0].substr(0, sepPos);
|
||||||
|
// search recursively and modify the tree structure
|
||||||
|
bool foundAndModified = _rootFolder.removeFromStructure(linarPathArray);
|
||||||
|
if (foundAndModified)
|
||||||
|
{
|
||||||
|
bool isRemoved = _pFileBrowser->deleteFromTree(rootPath, nullptr, linarPathArray);
|
||||||
|
if (not isRemoved)
|
||||||
|
MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printStr(TEXT("removeFromStructure pb"));
|
||||||
|
}
|
||||||
|
else if (action == FILE_ACTION_RENAMED_NEW_NAME)
|
||||||
|
{
|
||||||
|
generic_string rootPath = file2Change[0].substr(0, sepPos);
|
||||||
|
|
||||||
|
size_t sepPos2 = file2Change[1].find(separator);
|
||||||
|
if (sepPos2 == generic_string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
generic_string pathSuffix2 = file2Change[1].substr(sepPos2 + separator.length(), file2Change[1].length() - 1);
|
||||||
|
vector<generic_string> linarPathArray2 = split(pathSuffix2, '\\');
|
||||||
|
|
||||||
|
bool foundAndModified = _rootFolder.renameInStructure(linarPathArray, linarPathArray2);
|
||||||
|
if (foundAndModified)
|
||||||
|
{
|
||||||
|
bool isRenamed = _pFileBrowser->renameInTree(rootPath, nullptr, linarPathArray, linarPathArray2);
|
||||||
|
if (not isRenamed)
|
||||||
|
MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printStr(TEXT("removeFromStructure pb"));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1191,7 +1296,7 @@ bool FolderUpdater::updateTree(DWORD action, const std::vector<generic_string> &
|
|||||||
DWORD WINAPI FolderUpdater::watching(void *params)
|
DWORD WINAPI FolderUpdater::watching(void *params)
|
||||||
{
|
{
|
||||||
FolderUpdater *thisFolderUpdater = (FolderUpdater *)params;
|
FolderUpdater *thisFolderUpdater = (FolderUpdater *)params;
|
||||||
const TCHAR *dir2Watch = (thisFolderUpdater->_rootFolder)._path.c_str();
|
const TCHAR *dir2Watch = (thisFolderUpdater->_rootFolder)._rootPath.c_str();
|
||||||
|
|
||||||
const DWORD dwNotificationFlags = FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;
|
const DWORD dwNotificationFlags = FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
|
|
||||||
|
@ -60,52 +60,48 @@
|
|||||||
|
|
||||||
class TiXmlNode;
|
class TiXmlNode;
|
||||||
|
|
||||||
class changeInfo final
|
|
||||||
{
|
|
||||||
friend class FolderInfo;
|
|
||||||
public:
|
|
||||||
enum folderChangeAction{
|
|
||||||
add, remove, rename
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isFile; // true: file, false: folder
|
|
||||||
generic_string _fullFilePath;
|
|
||||||
std::vector<generic_string> _relativePath;
|
|
||||||
folderChangeAction _action;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FileInfo final
|
class FileInfo final
|
||||||
{
|
{
|
||||||
friend class FileBrowser;
|
friend class FileBrowser;
|
||||||
friend class FolderInfo;
|
friend class FolderInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileInfo(const generic_string & fn) { _path = fn; };
|
FileInfo(const generic_string & name, FolderInfo *parent) : _name(name), _parent(parent) {};
|
||||||
generic_string getLabel() { return ::PathFindFileName(_path.c_str()); };
|
generic_string getName() const { return _name; };
|
||||||
|
void setName(generic_string name) { _name = name; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
generic_string _path;
|
FileInfo(){}; // constructor by default is forbidden
|
||||||
|
FolderInfo *_parent = nullptr;
|
||||||
|
generic_string _name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FolderInfo final
|
class FolderInfo final
|
||||||
{
|
{
|
||||||
friend class FileBrowser;
|
friend class FileBrowser;
|
||||||
friend class FolderUpdater;
|
friend class FolderUpdater;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setPath(generic_string dn) { _path = dn; };
|
FolderInfo(const generic_string & name, FolderInfo *parent) : _name(name), _parent(parent) {};
|
||||||
void addFile(generic_string fn) { _files.push_back(FileInfo(fn)); };
|
void setRootPath(generic_string rootPath) { _rootPath = rootPath; };
|
||||||
|
generic_string getRootPath() const { return _rootPath; };
|
||||||
|
void setName(generic_string name) { _name = name; };
|
||||||
|
generic_string getName() const { return _name; };
|
||||||
|
void addFile(generic_string fn) { _files.push_back(FileInfo(fn, this)); };
|
||||||
void addSubFolder(FolderInfo subDirectoryStructure) { _subFolders.push_back(subDirectoryStructure); };
|
void addSubFolder(FolderInfo subDirectoryStructure) { _subFolders.push_back(subDirectoryStructure); };
|
||||||
bool compare(const FolderInfo & struct2compare, std::vector<changeInfo> & result);
|
|
||||||
static bool makeDiff(FolderInfo & struct1, FolderInfo & struct2static, std::vector<changeInfo> result);
|
bool addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray);
|
||||||
generic_string getLabel();
|
bool removeFromStructure(std::vector<generic_string> linarPathArray);
|
||||||
|
bool renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FolderInfo(){}; // constructor by default is forbidden
|
||||||
std::vector<FolderInfo> _subFolders;
|
std::vector<FolderInfo> _subFolders;
|
||||||
std::vector<FileInfo> _files;
|
std::vector<FileInfo> _files;
|
||||||
generic_string _path;
|
FolderInfo *_parent = nullptr;
|
||||||
generic_string _contentHash;
|
generic_string _name;
|
||||||
|
generic_string _rootPath; // set only for root folder; empty for normal folder
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BrowserNodeType {
|
enum BrowserNodeType {
|
||||||
@ -115,17 +111,16 @@ enum BrowserNodeType {
|
|||||||
class FolderUpdater {
|
class FolderUpdater {
|
||||||
friend class FileBrowser;
|
friend class FileBrowser;
|
||||||
public:
|
public:
|
||||||
FolderUpdater(FolderInfo fi, HWND hFileBrowser) : _rootFolder(fi), _hFileBrowser(hFileBrowser) {};
|
FolderUpdater(FolderInfo fi, FileBrowser *pFileBrowser) : _rootFolder(fi), _pFileBrowser(pFileBrowser) {};
|
||||||
~FolderUpdater() {};
|
~FolderUpdater() {};
|
||||||
bool updateTree(DWORD action, const std::vector<generic_string> & file2Change); // postMessage to FileBrowser to upgrade GUI
|
bool updateTree(DWORD action, const std::vector<generic_string> & file2Change); // postMessage to FileBrowser to upgrade GUI
|
||||||
|
|
||||||
void startWatcher();
|
void startWatcher();
|
||||||
void stopWatcher();
|
void stopWatcher();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FolderInfo _rootFolder;
|
FolderInfo _rootFolder;
|
||||||
HWND _hFileBrowser = nullptr;
|
FileBrowser *_pFileBrowser = nullptr;
|
||||||
HANDLE _watchThreadHandle = nullptr;
|
HANDLE _watchThreadHandle = nullptr;
|
||||||
HANDLE _EventHandle = nullptr;
|
HANDLE _EventHandle = nullptr;
|
||||||
|
|
||||||
@ -157,6 +152,13 @@ public:
|
|||||||
|
|
||||||
void addRootFolder(generic_string);
|
void addRootFolder(generic_string);
|
||||||
|
|
||||||
|
HTREEITEM getRootFromFullPath(generic_string rootPath);
|
||||||
|
HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, generic_string);
|
||||||
|
|
||||||
|
bool addInTree(generic_string rootPath, generic_string addItemFullPath, HTREEITEM node, std::vector<generic_string> linarPathArray);
|
||||||
|
bool deleteFromTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray);
|
||||||
|
bool renameInTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TreeView _treeView;
|
TreeView _treeView;
|
||||||
HIMAGELIST _hImaLst;
|
HIMAGELIST _hImaLst;
|
||||||
@ -170,9 +172,8 @@ protected:
|
|||||||
void initMenus();
|
void initMenus();
|
||||||
void destroyMenus();
|
void destroyMenus();
|
||||||
BOOL setImageList(int root_clean_id, int root_dirty_id, int project_id, int open_node_id, int closed_node_id, int leaf_id, int ivalid_leaf_id);
|
BOOL setImageList(int root_clean_id, int root_dirty_id, int project_id, int open_node_id, int closed_node_id, int leaf_id, int ivalid_leaf_id);
|
||||||
void addFiles(HTREEITEM hTreeItem);
|
|
||||||
void recursiveAddFilesFrom(const TCHAR *folderPath, HTREEITEM hTreeItem);
|
HTREEITEM createNewFolder(HTREEITEM hTreeItem, const TCHAR *folderName);
|
||||||
HTREEITEM addFolder(HTREEITEM hTreeItem, const TCHAR *folderName);
|
|
||||||
|
|
||||||
generic_string getRelativePath(const generic_string & fn, const TCHAR *workSpaceFileName);
|
generic_string getRelativePath(const generic_string & fn, const TCHAR *workSpaceFileName);
|
||||||
void buildProjectXml(TiXmlNode *root, HTREEITEM hItem, const TCHAR* fn2write);
|
void buildProjectXml(TiXmlNode *root, HTREEITEM hItem, const TCHAR* fn2write);
|
||||||
|
@ -91,6 +91,20 @@ bool TreeView::setItemParam(HTREEITEM Item2Set, const TCHAR *paramStr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TreeView::renameItem(HTREEITEM Item2Set, const TCHAR *newName)
|
||||||
|
{
|
||||||
|
if (not Item2Set || not newName)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TVITEM tvItem;
|
||||||
|
tvItem.hItem = Item2Set;
|
||||||
|
tvItem.mask = TVIF_TEXT;
|
||||||
|
tvItem.pszText = (LPWSTR)newName;
|
||||||
|
tvItem.cchTextMax = MAX_PATH;
|
||||||
|
SendMessage(_hSelf, TVM_SETITEM, 0, (LPARAM)&tvItem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
HTREEITEM TreeView::addItem(const TCHAR *itemName, HTREEITEM hParentItem, int iImage, const TCHAR *filePath)
|
HTREEITEM TreeView::addItem(const TCHAR *itemName, HTREEITEM hParentItem, int iImage, const TCHAR *filePath)
|
||||||
{
|
{
|
||||||
TVITEM tvi;
|
TVITEM tvi;
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
HTREEITEM searchSubItemByName(const TCHAR *itemName, HTREEITEM hParentItem);
|
HTREEITEM searchSubItemByName(const TCHAR *itemName, HTREEITEM hParentItem);
|
||||||
void removeItem(HTREEITEM hTreeItem);
|
void removeItem(HTREEITEM hTreeItem);
|
||||||
void removeAllItems();
|
void removeAllItems();
|
||||||
|
bool renameItem(HTREEITEM Item2Set, const TCHAR *newName);
|
||||||
|
|
||||||
HTREEITEM getChildFrom(HTREEITEM hTreeItem) const {
|
HTREEITEM getChildFrom(HTREEITEM hTreeItem) const {
|
||||||
return TreeView_GetChild(_hSelf, hTreeItem);
|
return TreeView_GetChild(_hSelf, hTreeItem);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user