From 4d709dccd2e0758a9a5b7cc709118cd2789c2e31 Mon Sep 17 00:00:00 2001 From: ObsidianNA <42883452+ObsidianNA@users.noreply.github.com> Date: Tue, 9 Jul 2019 21:36:58 -0400 Subject: [PATCH] Recent Files List Overview: Added a Pop-up menu named 'Open Recent' under the 'File' menu bar item that lists 10 recently opened files. - It stores the paths of opened games inside a file named 'recent.txt' in the same folder where the xenia.exe is located. - If the file doesn't exits, the program creates it, then paths are stored when a new file is opened. - Each time a file is opened, the program compares stored paths with the new one, if it exists then the path is moved to the top of the list to indicate that it is the most recent file opened. - 'Open Recent' entries are refreshed once xenia is re-started. --- src/xenia/app/emulator_window.cc | 87 ++++++++++++++++++++++++++++++++ src/xenia/app/emulator_window.h | 3 ++ 2 files changed, 90 insertions(+) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 1aa44578e..62ff25948 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -28,6 +28,9 @@ // Autogenerated by `xb premake`. #include "build/version.h" +// For recent files R/W +#include +#include DECLARE_bool(debug); DEFINE_int32(window_height, 720, "Window height", "UI"); @@ -186,10 +189,37 @@ bool EmulatorWindow::Initialize() { // FIXME: This code is really messy. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); + // Recent Sub tab + auto recent_list = MenuItem::Create(MenuItem::Type::kPopup, "&Open Recent"); + //******Add Recent PATHS to menu*************************************** + std::string lines[10]; + std::ifstream recent_file_read("recent.txt"); + int i = 0; + // Convert from UTF-8 to wide using helper function xe::to_wstring() + if (recent_file_read.is_open()) { + while ((i < 10) && getline(recent_file_read, lines[i])) { + // Save paths to memory + global_recent_paths_[i] = xe::to_path(lines[i]); + // Add most recently opened files to menu + if (lines[i] != "" && lines[i] != "\n") { + recent_list->AddChild( + MenuItem::Create(MenuItem::Type::kString, global_recent_paths_[i].u8string(), + std::bind(&EmulatorWindow::RecentList, this, i))); + } else { + break; + } + i++; + } + recent_file_read.close(); + } + //**************************************************************************** { file_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "&Open...", "Ctrl+O", std::bind(&EmulatorWindow::FileOpen, this))); + // Add Recent List Tab to file tab + file_menu->AddChild(std::move(recent_list)); + file_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "Close", std::bind(&EmulatorWindow::FileClose, this))); @@ -301,6 +331,48 @@ void EmulatorWindow::FileDrop(const std::filesystem::path& filename) { } } +// Add new path to recent storage or prioritize if it already exist +void EmulatorWindow::RecentListUpdater(const std::filesystem::path& path) { + //*******Save abs_path to recent as UTF-8****************************** + std::string u8_path = path.u8string(); + + // Write to 'recent.txt' file + std::string lines[10]; + int i = 0; + int path_poss = 0; + bool path_is_in = false; + // Open file "recent.txt" to read values + std::ifstream recent_file_read("recent.txt"); + if (recent_file_read.is_open()) { + // Loop until end of document or 10 lines are read, which ever comes first + while (getline(recent_file_read, lines[i]) && (i < 9)) { + if (u8_path.compare(lines[i]) == 0) { + path_is_in = true; + path_poss = i; + } + i++; + } + recent_file_read.close(); + } + // Move lines + if (!path_is_in) { + path_poss = 9; + } + for (i = path_poss; i > 0; i--) { + lines[i] = lines[i - 1]; + } + // Add all lines to file + lines[0] = u8_path; + std::ofstream recent_file_write("recent.txt"); + for (i = 0; i < 10; i++) { + if (lines[i] != "" && lines[i] != "\n") { + recent_file_write << lines[i] << std::endl; + } + } + recent_file_write.close(); + //***************************************************** +} + void EmulatorWindow::FileOpen() { std::filesystem::path path; @@ -326,6 +398,8 @@ void EmulatorWindow::FileOpen() { if (!path.empty()) { // Normalize the path and make absolute. auto abs_path = std::filesystem::absolute(path); + EmulatorWindow::RecentListUpdater(abs_path); + auto result = emulator_->LaunchPath(abs_path); if (XFAILED(result)) { // TODO: Display a message box. @@ -334,6 +408,19 @@ void EmulatorWindow::FileOpen() { } } +// Launch recently opened files +void EmulatorWindow::RecentList(int index) { + if (!global_recent_paths_[index].empty()) { + EmulatorWindow::RecentListUpdater(global_recent_paths_[index]); + + auto result = emulator_->LaunchPath(global_recent_paths_[index]); + if (XFAILED(result)) { + // TODO: Display a message box. + XELOGE("Failed to launch target: %.8X", result); + } + } +} + void EmulatorWindow::FileClose() { if (emulator_->is_title_open()) { emulator_->TerminateTitle(); diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 4d29d9a5b..99f447288 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -46,6 +46,8 @@ class EmulatorWindow { void FileDrop(const std::filesystem::path& filename); void FileOpen(); + void RecentListUpdater(const std::filesystem::path& path); + void RecentList(int index); void FileClose(); void ShowContentDirectory(); void CheckHideCursor(); @@ -63,6 +65,7 @@ class EmulatorWindow { std::unique_ptr loop_; std::unique_ptr window_; std::string base_title_; + std::filesystem::path global_recent_paths_[10]; uint64_t cursor_hide_time_ = 0; bool initializing_shader_storage_ = false; };