diff --git a/Mods/vcmi/Sprites/ScSelC.json b/Mods/vcmi/Sprites/ScSelC.json index 7d8279cc3..499e5740e 100644 --- a/Mods/vcmi/Sprites/ScSelC.json +++ b/Mods/vcmi/Sprites/ScSelC.json @@ -2,6 +2,7 @@ "basepath" : "mapFormatIcons/", "images" : [ - { "frame" : 3, "file" : "vcmi1.png"} + { "frame" : 3, "file" : "vcmi1.png"}, + { "frame" : 99, "file" : "folder.png"} ] } \ No newline at end of file diff --git a/Mods/vcmi/Sprites/mapFormatIcons/folder.png b/Mods/vcmi/Sprites/mapFormatIcons/folder.png new file mode 100644 index 000000000..44547ef38 Binary files /dev/null and b/Mods/vcmi/Sprites/mapFormatIcons/folder.png differ diff --git a/client/lobby/CSavingScreen.cpp b/client/lobby/CSavingScreen.cpp index 562643a92..1126fb444 100644 --- a/client/lobby/CSavingScreen.cpp +++ b/client/lobby/CSavingScreen.cpp @@ -70,7 +70,7 @@ void CSavingScreen::saveGame() if(!(tabSel && tabSel->inputName && tabSel->inputName->getText().size())) return; - std::string path = "Saves/" + tabSel->inputName->getText(); + std::string path = "Saves/" + tabSel->curFolder + tabSel->inputName->getText(); auto overWrite = [this, path]() -> void { diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index 198678822..cc0aceb4b 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -345,14 +345,17 @@ void SelectionTab::showPopupWindow(const Point & cursorPosition) if(py >= curItems.size()) return; - std::string text = boost::str(boost::format("{%1%}\r\n\r\n%2%:\r\n%3%") % curItems[py]->getName() % CGI->generaltexth->translate("vcmi.lobby.filename") % curItems[py]->fileURI); - if(curItems[py]->date != "") - text += boost::str(boost::format("\r\n\r\n%1%:\r\n%2%") % CGI->generaltexth->translate("vcmi.lobby.creationDate") % curItems[py]->date); + if(!curItems[py]->isFolder) + { + std::string text = boost::str(boost::format("{%1%}\r\n\r\n%2%:\r\n%3%") % curItems[py]->getName() % CGI->generaltexth->translate("vcmi.lobby.filename") % curItems[py]->fileURI); + if(curItems[py]->date != "") + text += boost::str(boost::format("\r\n\r\n%1%:\r\n%2%") % CGI->generaltexth->translate("vcmi.lobby.creationDate") % curItems[py]->date); - CRClickPopup::createAndPush(text); + CRClickPopup::createAndPush(text); + } } -std::tuple SelectionTab::checkSubfolder(std::string path) +std::tuple SelectionTab::checkSubfolder(std::string path) { std::string folderName = ""; bool parentExists = (curFolder != ""); @@ -364,13 +367,11 @@ std::tuple SelectionTab::checkSubfolder(std::string pat filetree.erase(filetree.begin()); std::string pathWithoutPrefix = boost::algorithm::join(filetree, "/"); - std::string folder = boost::filesystem::path(pathWithoutPrefix).parent_path().string(); + std::string baseFolder = boost::filesystem::path(pathWithoutPrefix).parent_path().string(); - if(boost::algorithm::starts_with(folder, curFolder)) + if(boost::algorithm::starts_with(baseFolder, curFolder)) { - folder = folder.substr(curFolder.size()); - if(boost::algorithm::starts_with(folder, "/")) - folder = folder.substr(1); + std::string folder = baseFolder.substr(curFolder.size()); if(folder != "") { @@ -383,50 +384,40 @@ std::tuple SelectionTab::checkSubfolder(std::string pat if(boost::count(pathWithoutPrefix.substr(curFolder.size()), '/') == 0) fileInFolder = true; - return {folderName, parentExists, fileInFolder}; + return {folderName, baseFolder, parentExists, fileInFolder}; } // A new size filter (Small, Medium, ...) has been selected. Populate // selMaps with the relevant data. void SelectionTab::filter(int size, bool selectFirst) { - std::string path = ""; - curItems.clear(); - if(tabType == ESelectionScreen::campaignList) + for(auto elem : allItems) { - for(auto elem : allItems) - curItems.push_back(elem); - } - else - { - for(auto elem : allItems) + if((elem->mapHeader && (!size || elem->mapHeader->width == size)) || tabType == ESelectionScreen::campaignList) { - if(elem->mapHeader && (!size || elem->mapHeader->width == size)) + auto [folderName, baseFolder, parentExists, fileInFolder] = checkSubfolder(elem->fileURI); + + if(parentExists) { - auto [folderName, parentExists, fileInFolder] = checkSubfolder(elem->fileURI); - - if(parentExists) - { - auto folder = std::make_shared(); - folder->isFolder = true; - folder->folderName = ".."; - if (boost::range::find_if(curItems, [](std::shared_ptr e) { return e->folderName == ".."; }) == curItems.end()) { - curItems.push_back(folder); - } - } - - std::shared_ptr folder = std::make_shared(); + auto folder = std::make_shared(); folder->isFolder = true; - folder->folderName = folderName; - if (boost::range::find_if(curItems, [folder](std::shared_ptr e) { return e->folderName == folder->folderName; }) == curItems.end() && folderName != "") { + folder->folderName = ".."; + if (boost::range::find_if(curItems, [](std::shared_ptr e) { return e->folderName == ".."; }) == curItems.end()) { curItems.push_back(folder); - } - - if(fileInFolder) - curItems.push_back(elem); + } } + + std::shared_ptr folder = std::make_shared(); + folder->isFolder = true; + folder->folderName = folderName; + if (boost::range::find_if(curItems, [folder](std::shared_ptr e) { return e->folderName == folder->folderName; }) == curItems.end() && folderName != "") { + curItems.push_back(folder); + } + + if(fileInFolder) + curItems.push_back(elem); } } @@ -472,8 +463,9 @@ void SelectionTab::sort() std::stable_sort(curItems.begin(), curItems.end(), mapSorter(generalSortingBy)); std::stable_sort(curItems.begin(), curItems.end(), mapSorter(sortingBy)); + int firstMap = boost::range::find_if(curItems, [](std::shared_ptr e) { return !e->isFolder; }) - curItems.begin(); if(!sortModeAscending) - std::reverse(curItems.begin(), curItems.end()); + std::reverse(std::next(curItems.begin(), firstMap), curItems.end()); updateListItems(); redraw(); @@ -496,8 +488,6 @@ void SelectionTab::select(int position) else if(position >= listItems.size()) slider->scrollBy(position - (int)listItems.size() + 1); - rememberCurrentSelection(); - if(curItems[py]->isFolder) { if(curItems[py]->folderName == "..") { @@ -510,9 +500,13 @@ void SelectionTab::select(int position) else curFolder += curItems[py]->folderName + "/"; filter(0); + slider->scrollTo(0); + return; } + rememberCurrentSelection(); + if(inputName && inputName->isActive()) { auto filename = *CResourceHandler::get("local")->getResourceName(ResourceID(curItems[py]->fileURI, EResType::SAVEGAME)); @@ -594,6 +588,10 @@ int SelectionTab::getLine(const Point & clickPos) const void SelectionTab::selectFileName(std::string fname) { boost::to_upper(fname); + + auto [folderName, baseFolder, parentExists, fileInFolder] = checkSubfolder(fname); + curFolder = baseFolder != "" ? baseFolder + "/" : ""; + for(int i = (int)curItems.size() - 1; i >= 0; i--) { if(curItems[i]->fileURI == fname) @@ -604,12 +602,13 @@ void SelectionTab::selectFileName(std::string fname) } } + filter(0); selectAbs(-1); } std::shared_ptr SelectionTab::getSelectedMapInfo() const { - return curItems.empty() ? nullptr : curItems[selectionPos]; + return curItems.empty() || curItems[selectionPos]->isFolder ? nullptr : curItems[selectionPos]; } void SelectionTab::rememberCurrentSelection() @@ -799,7 +798,8 @@ void SelectionTab::ListItem::updateItem(std::shared_ptr info, bool { labelAmountOfPlayers->disable(); labelMapSizeLetter->disable(); - iconFormat->disable(); + iconFormat->enable(); + iconFormat->setFrame(99); iconVictoryCondition->disable(); iconLossCondition->disable(); labelNumberOfCampaignMaps->disable(); diff --git a/client/lobby/SelectionTab.h b/client/lobby/SelectionTab.h index fe5eef787..a2c45f125 100644 --- a/client/lobby/SelectionTab.h +++ b/client/lobby/SelectionTab.h @@ -106,7 +106,7 @@ private: ESelectionScreen tabType; Rect inputNameRect; - std::tuple checkSubfolder(std::string path); + std::tuple checkSubfolder(std::string path); bool isMapSupported(const CMapInfo & info); void parseMaps(const std::unordered_set & files);