diff --git a/src/ImageSelectState.cpp b/src/ImageSelectState.cpp index b837709..fe5da74 100644 --- a/src/ImageSelectState.cpp +++ b/src/ImageSelectState.cpp @@ -28,6 +28,7 @@ https://github.com/sago007/saland #include "PuzzleSingleImageState.hpp" #include "sago_common.hpp" #include "SagoImGui.hpp" +#include "config.hpp" static void DrawRect(SDL_Renderer* target, int topx, int topy, int height, int width, const std::string& name) { const int size = 32; @@ -144,6 +145,39 @@ void ImageSelectState::Draw(SDL_Renderer* target) { imageNameFields[image_number].Draw(target, text_x_physical, text_y_physical, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom); } + + // Draw favorite indicator as ImGui button overlay + if (image_number < imageList.size()) { + bool isFavorite = IsFavorite(imageList[image_number]); + int star_x_physical, star_y_physical; + logicalResize.LogicalToPhysical( + frame_logical.x + frame_size - 40, + frame_logical.y + 10, + star_x_physical, star_y_physical); + + ImGui::SetNextWindowPos(ImVec2(star_x_physical, star_y_physical)); + ImGui::SetNextWindowSize(ImVec2(0, 0)); + ImGui::Begin(("##favorite" + std::to_string(image_number)).c_str(), + nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoBackground); + + const char* starText = isFavorite ? "★" : "☆"; + if (ImGui::Button(starText)) { + if (isFavorite) { + RemoveFavorite(imageList[image_number]); + } else { + AddFavorite(imageList[image_number]); + } + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(isFavorite ? "Remove from favorites" : "Add to favorites"); + } + + ImGui::End(); + } } ImGui::BeginMainMenuBar(); @@ -153,6 +187,18 @@ void ImageSelectState::Draw(SDL_Renderer* target) { } ImGui::EndMenu(); } + if (ImGui::BeginMenu("View")) { + if (ImGui::MenuItem("Show Only Favorites", nullptr, showOnlyFavorites)) { + showOnlyFavorites = !showOnlyFavorites; + // Reload the image list with the new filter + imageList.clear(); + imageNameFields.clear(); + imageHolders.clear(); + firstImage = 0; + Init(); + } + ImGui::EndMenu(); + } ImGui::EndMainMenuBar(); ImGui::Begin("Page control"); if (ImGui::Button("Next page")) { @@ -179,6 +225,11 @@ void ImageSelectState::Update() { if (SDL_GetMouseState(nullptr,nullptr)&SDL_BUTTON(1) && globalData.mouseUp) { globalData.mouseUp = false; + // Don't process clicks if ImGui wants to capture the mouse (e.g., clicking on buttons) + if (ImGui::GetIO().WantCaptureMouse) { + return; + } + // Convert physical mouse coordinates to logical coordinates int mouse_x_logical, mouse_y_logical; logicalResize.PhysicalToLogical(globalData.mousex, globalData.mousey, mouse_x_logical, mouse_y_logical); @@ -263,13 +314,20 @@ void ImageSelectState::Init() { if (!folder.empty()) { for (const auto& entry : std::filesystem::directory_iterator(folder)) { if (entry.is_regular_file() && (HasExtension(entry.path().string(), ".jpg") || HasExtension(entry.path().string(), ".jpeg") || HasExtension(entry.path().string(), ".png") ) ) { + std::string imagePath = entry.path().string(); + + // If showOnlyFavorites is enabled, skip non-favorite images + if (showOnlyFavorites && !IsFavorite(imagePath)) { + continue; + } + std::cout << entry.path() << std::endl; - imageList.push_back(entry.path().string()); + imageList.push_back(imagePath); sago::SagoTextField field; setFontText(globalData.dataHolder, field, entry.path().filename().string().c_str()); imageNameFields.push_back(std::move(field)); imageHolders.emplace_back(); - imageHolders.back().LoadPictureFromFileLazy(entry.path().string()); + imageHolders.back().LoadPictureFromFileLazy(imagePath); } } } diff --git a/src/ImageSelectState.hpp b/src/ImageSelectState.hpp index 7e5f8b8..70b11ed 100644 --- a/src/ImageSelectState.hpp +++ b/src/ImageSelectState.hpp @@ -53,6 +53,7 @@ public: private: bool isActive = true; + bool showOnlyFavorites = false; sago::SagoLogicalResize logicalResize; }; diff --git a/src/config.cpp b/src/config.cpp index 490016f..2067fb9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -25,6 +25,7 @@ SOFTWARE. #include "config.hpp" #include "os.hpp" #include +#include std::map LoadConfigMap() { std::map config; @@ -107,3 +108,73 @@ std::string GetConfigString(const std::map& config, co void SetConfigString(std::map& config, const std::string& key, const std::string& value) { config[key] = value; } + +std::vector LoadFavorites() { + std::vector favorites; + std::string favoritesPath = getPathToSaveFiles() + "/favorites.txt"; + std::ifstream favoritesFile(favoritesPath); + + if (favoritesFile.is_open()) { + std::string line; + while (std::getline(favoritesFile, line)) { + if (!line.empty() && line[0] != '#') { + favorites.push_back(line); + } + } + favoritesFile.close(); + } + + return favorites; +} + +void SaveFavorites(const std::vector& favorites) { + std::string favoritesPath = getPathToSaveFiles() + "/favorites.txt"; + std::ofstream favoritesFile(favoritesPath); + + if (favoritesFile.is_open()) { + favoritesFile << "# Favorite images - one absolute path per line" << std::endl; + for (const auto& favorite : favorites) { + favoritesFile << favorite << std::endl; + } + favoritesFile.close(); + } +} + +void AddFavorite(const std::string& imagePath) { + std::vector favorites = LoadFavorites(); + + // Check if already in favorites + for (const auto& fav : favorites) { + if (fav == imagePath) { + return; + } + } + + favorites.push_back(imagePath); + SaveFavorites(favorites); +} + +void RemoveFavorite(const std::string& imagePath) { + std::vector favorites = LoadFavorites(); + std::vector newFavorites; + + for (const auto& fav : favorites) { + if (fav != imagePath) { + newFavorites.push_back(fav); + } + } + + SaveFavorites(newFavorites); +} + +bool IsFavorite(const std::string& imagePath) { + std::vector favorites = LoadFavorites(); + + for (const auto& fav : favorites) { + if (fav == imagePath) { + return true; + } + } + + return false; +} diff --git a/src/config.hpp b/src/config.hpp index 11a41ea..0100d37 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -27,6 +27,7 @@ SOFTWARE. #include #include +#include /** * @brief Loads configuration from file into a map @@ -91,4 +92,35 @@ std::string GetConfigString(const std::map& config, co */ void SetConfigString(std::map& config, const std::string& key, const std::string& value); +/** + * @brief Loads the list of favorite image paths + * @return Vector of absolute paths to favorite images + */ +std::vector LoadFavorites(); + +/** + * @brief Saves the list of favorite image paths + * @param favorites Vector of absolute paths to favorite images + */ +void SaveFavorites(const std::vector& favorites); + +/** + * @brief Adds an image path to favorites + * @param imagePath Absolute path to the image + */ +void AddFavorite(const std::string& imagePath); + +/** + * @brief Removes an image path from favorites + * @param imagePath Absolute path to the image + */ +void RemoveFavorite(const std::string& imagePath); + +/** + * @brief Checks if an image path is in favorites + * @param imagePath Absolute path to the image + * @return true if the image is a favorite, false otherwise + */ +bool IsFavorite(const std::string& imagePath); + #endif // CONFIG_HPP