diff --git a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp index d12aa9e83..8606349b9 100644 --- a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp +++ b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp @@ -580,7 +580,7 @@ POINT FileBrowser::getMenuDisplayPoint(int iButton) 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); @@ -634,12 +634,12 @@ void FileBrowser::popupMenuCmd(int cmdID) case IDM_FILEBROWSER_RENAME : TreeView_EditLabel(_treeView.getHSelf(), hTreeItem); break; - + case IDM_FILEBROWSER_NEWFOLDER : { NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance())->getNativeLangSpeaker(); generic_string newFolderLabel = pNativeSpeaker->getAttrNameStr(PM_NEWFOLDERNAME, "ProjectManager", "NewFolderName"); - addFolder(hTreeItem, newFolderLabel.c_str()); + createNewFolder(hTreeItem, newFolderLabel.c_str()); } break; @@ -654,7 +654,8 @@ void FileBrowser::popupMenuCmd(int cmdID) _treeView.moveUp(hTreeItem); } break; - + + /* case IDM_FILEBROWSER_ADDFILES : { addFiles(hTreeItem); @@ -662,6 +663,7 @@ void FileBrowser::popupMenuCmd(int cmdID) _treeView.setItemImage(hTreeItem, INDEX_OPEN_NODE, INDEX_OPEN_NODE); } break; + */ 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 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 & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir) { - directoryStructure.setPath(dir); + if (directoryStructure._parent == nullptr) // Root! + directoryStructure.setRootPath(dir); generic_string dirFilter(dir); dirFilter += TEXT("*.*"); @@ -803,7 +733,7 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector patterns2Match; patterns2Match.push_back(TEXT("*.*")); - FolderInfo directoryStructure; + TCHAR *label = ::PathFindFileName(rootFolderPath.c_str()); + FolderInfo directoryStructure(label, nullptr); getDirectoryStructure(rootFolderPath.c_str(), patterns2Match, directoryStructure, true, false); HTREEITEM hRootItem = createFolderItemsFromDirStruct(nullptr, directoryStructure); _treeView.expand(hRootItem); - _folderUpdaters.push_back(FolderUpdater(directoryStructure, _hSelf)); + _folderUpdaters.push_back(FolderUpdater(directoryStructure, this)); _folderUpdaters[_folderUpdaters.size() - 1].startWatcher(); } 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; - 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 { - 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) @@ -899,218 +826,328 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con for (size_t i = 0; i < directoryStructure._files.size(); ++i) { - TCHAR filePath[MAX_PATH]; - 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.addItem(directoryStructure._files[i]._name.c_str(), hFolderItem, INDEX_LEAF); } _treeView.fold(hParentItem); return hFolderItem; } -bool FolderInfo::compare(const FolderInfo & struct2compare, std::vector & 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; - } - else // folder is renamed - { - // put result in the vector - changeInfo info; - info._action = info.rename; - info._fullFilePath = struct2compare._path; - return false; + childNodeFound = hItemNode; } } - else // sub-folders or files/sub-files deleted or renamed + return childNodeFound; +} + +bool FileBrowser::addInTree(generic_string rootPath, generic_string addItemFullPath, HTREEITEM node, vector 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 - { - return true; // everything could be fine - } + // Search + if ((node = getRootFromFullPath(rootPath)) == nullptr) + return false; + } - //check folder (maybe go deeper) - for (size_t i = 0; i < _subFolders.size(); ++i) + if (linarPathArray.size() == 1) + { + // 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; - for (size_t j = 0; j < struct2compare._subFolders.size(); ++j) + _treeView.addItem(linarPathArray[0].c_str(), node, INDEX_CLOSED_NODE); + } + 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) && - (_subFolders[i]._contentHash == struct2compare._subFolders[j]._contentHash)) - { - 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); + // search recursively the node for an action + linarPathArray.erase(linarPathArray.begin()); + return addInTree(rootPath, addItemFullPath, hItemNode, linarPathArray); } } + return false; + } +} - //check files +bool FileBrowser::deleteFromTree(generic_string rootPath, HTREEITEM node, std::vector 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 linarPathArrayFrom, std::vector 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 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 linarPathArray) +{ + if (linarPathArray.size() == 1) // could be file or folder + { for (size_t i = 0; i < _files.size(); ++i) { - bool isFound = false; - for (size_t j = 0; not isFound && j < struct2compare._files.size(); ++j) + if (_files[i].getName() == linarPathArray[0]) { - if (_files[i]._path == struct2compare._files[j]._path) - isFound = 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); + // remove this file + _files.erase(_files.begin() + i); + return true; } } - /* - for (size_t i = 0; i < struct2compare._files.size(); ++i) + + for (size_t i = 0; i < _subFolders.size(); ++i) { - bool isFound = false; - for (size_t j = 0; not isFound && j < _files.size(); ++j) + if (_subFolders[i].getName() == linarPathArray[0]) { - if (_files[i]._path == struct2compare._files[j]._path) - isFound = 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); + // remove this folder + _subFolders.erase(_subFolders.begin() + i); + return true; } } - */ - 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 result) +bool FolderInfo::renameInStructure(std::vector linarPathArrayFrom, std::vector 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 - return true; + if (_files[i].getName() == linarPathArrayFrom[0]) + { + // 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 - changeInfo info; - info._action = info.rename; - info._fullFilePath = struct2._path; - result.push_back(info); - return false; + if (_subFolders[i].getName() == linarPathArrayFrom[0]) + { + // rename this folder + _subFolders[i].setName(linarPathArrayTo[0]); + return true; + } } + 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 - } - - //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 (_subFolders[i].getName() == linarPathArrayFrom[0]) { - if ((struct1._subFolders[i]._path == struct2._subFolders[j]._path) && - (struct1._subFolders[i]._contentHash == struct2._subFolders[j]._contentHash)) - { - 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); + linarPathArrayFrom.erase(linarPathArrayFrom.begin()); + linarPathArrayTo.erase(linarPathArrayTo.begin()); + return _subFolders[i].renameInStructure(linarPathArrayFrom, linarPathArrayTo); } } - - //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; + return false; } } -generic_string FolderInfo::getLabel() -{ - return ::PathFindFileName(_path.c_str()); -} - void FolderUpdater::startWatcher() { // no thread yet, create a event with non-signaled, to block all threads @@ -1144,45 +1181,113 @@ LPCWSTR explainAction(DWORD dwAction) } }; +vector split(const generic_string & string2split, TCHAR sep) +{ + vector 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 & file2Change) { - //TCHAR msg2show[1024]; - + /* + TCHAR msg2show[1024]; switch (action) { - case FILE_ACTION_ADDED: - //swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str()); - //printStr(msg2show); - //::PostMessage(thisFolderUpdater->_hFileBrowser, FB_ADDFILE, nullptr, (LPARAM)wstrFilename.GetString()); - break; + case FILE_ACTION_ADDED: + swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str()); + printStr(msg2show); + //::PostMessage(thisFolderUpdater->_hFileBrowser, FB_ADDFILE, nullptr, (LPARAM)wstrFilename.GetString()); + break; - case FILE_ACTION_REMOVED: - //swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str()); - //printStr(msg2show); + case FILE_ACTION_REMOVED: + swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str()); + printStr(msg2show); - break; + break; - case FILE_ACTION_RENAMED_NEW_NAME: - //swprintf(msg2show, L"%s from %s \rto %s", explainAction(action), file2Change[0].c_str(), file2Change[1].c_str()); - //printStr(msg2show); + case FILE_ACTION_RENAMED_NEW_NAME: + swprintf(msg2show, L"%s from %s \rto %s", explainAction(action), file2Change[0].c_str(), file2Change[1].c_str()); + printStr(msg2show); - break; + break; - default: - break; + default: + break; } + */ generic_string separator = TEXT("\\\\"); size_t sepPos = file2Change[0].find(separator); if (sepPos == generic_string::npos) return false; - generic_string rootPrefix = file2Change[0].substr(0, sepPos); 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 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 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; } @@ -1191,7 +1296,7 @@ bool FolderUpdater::updateTree(DWORD action, const std::vector & DWORD WINAPI FolderUpdater::watching(void *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; diff --git a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.h b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.h index 222722107..e9051224f 100644 --- a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.h +++ b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.h @@ -60,52 +60,48 @@ 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 _relativePath; - folderChangeAction _action; -}; - class FileInfo final { friend class FileBrowser; friend class FolderInfo; public: - FileInfo(const generic_string & fn) { _path = fn; }; - generic_string getLabel() { return ::PathFindFileName(_path.c_str()); }; + FileInfo(const generic_string & name, FolderInfo *parent) : _name(name), _parent(parent) {}; + generic_string getName() const { return _name; }; + void setName(generic_string name) { _name = name; }; private: - generic_string _path; + FileInfo(){}; // constructor by default is forbidden + FolderInfo *_parent = nullptr; + generic_string _name; }; + class FolderInfo final { friend class FileBrowser; friend class FolderUpdater; public: - void setPath(generic_string dn) { _path = dn; }; - void addFile(generic_string fn) { _files.push_back(FileInfo(fn)); }; + FolderInfo(const generic_string & name, FolderInfo *parent) : _name(name), _parent(parent) {}; + 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); }; - bool compare(const FolderInfo & struct2compare, std::vector & result); - static bool makeDiff(FolderInfo & struct1, FolderInfo & struct2static, std::vector result); - generic_string getLabel(); + + bool addToStructure(generic_string & fullpath, std::vector linarPathArray); + bool removeFromStructure(std::vector linarPathArray); + bool renameInStructure(std::vector linarPathArrayFrom, std::vector linarPathArrayTo); private: + FolderInfo(){}; // constructor by default is forbidden std::vector _subFolders; std::vector _files; - generic_string _path; - generic_string _contentHash; + FolderInfo *_parent = nullptr; + generic_string _name; + generic_string _rootPath; // set only for root folder; empty for normal folder }; enum BrowserNodeType { @@ -115,17 +111,16 @@ enum BrowserNodeType { class FolderUpdater { friend class FileBrowser; public: - FolderUpdater(FolderInfo fi, HWND hFileBrowser) : _rootFolder(fi), _hFileBrowser(hFileBrowser) {}; + FolderUpdater(FolderInfo fi, FileBrowser *pFileBrowser) : _rootFolder(fi), _pFileBrowser(pFileBrowser) {}; ~FolderUpdater() {}; bool updateTree(DWORD action, const std::vector & file2Change); // postMessage to FileBrowser to upgrade GUI void startWatcher(); void stopWatcher(); - private: FolderInfo _rootFolder; - HWND _hFileBrowser = nullptr; + FileBrowser *_pFileBrowser = nullptr; HANDLE _watchThreadHandle = nullptr; HANDLE _EventHandle = nullptr; @@ -157,6 +152,13 @@ public: 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 linarPathArray); + bool deleteFromTree(generic_string rootPath, HTREEITEM node, std::vector linarPathArray); + bool renameInTree(generic_string rootPath, HTREEITEM node, std::vector linarPathArrayFrom, std::vector linarPathArrayTo); + protected: TreeView _treeView; HIMAGELIST _hImaLst; @@ -170,9 +172,8 @@ protected: void initMenus(); 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); - void addFiles(HTREEITEM hTreeItem); - void recursiveAddFilesFrom(const TCHAR *folderPath, HTREEITEM hTreeItem); - HTREEITEM addFolder(HTREEITEM hTreeItem, const TCHAR *folderName); + + HTREEITEM createNewFolder(HTREEITEM hTreeItem, const TCHAR *folderName); generic_string getRelativePath(const generic_string & fn, const TCHAR *workSpaceFileName); void buildProjectXml(TiXmlNode *root, HTREEITEM hItem, const TCHAR* fn2write); diff --git a/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp b/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp index e49a826bf..028f1bb0c 100644 --- a/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp +++ b/PowerEditor/src/WinControls/ProjectPanel/TreeView.cpp @@ -91,6 +91,20 @@ bool TreeView::setItemParam(HTREEITEM Item2Set, const TCHAR *paramStr) 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) { TVITEM tvi; diff --git a/PowerEditor/src/WinControls/ProjectPanel/TreeView.h b/PowerEditor/src/WinControls/ProjectPanel/TreeView.h index 26015a211..bc1a3d533 100644 --- a/PowerEditor/src/WinControls/ProjectPanel/TreeView.h +++ b/PowerEditor/src/WinControls/ProjectPanel/TreeView.h @@ -54,6 +54,7 @@ public: HTREEITEM searchSubItemByName(const TCHAR *itemName, HTREEITEM hParentItem); void removeItem(HTREEITEM hTreeItem); void removeAllItems(); + bool renameItem(HTREEITEM Item2Set, const TCHAR *newName); HTREEITEM getChildFrom(HTREEITEM hTreeItem) const { return TreeView_GetChild(_hSelf, hTreeItem);