From 46d19eeb1f12e8b7da337962f6ca0f9cd03cc0e2 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 24 Apr 2021 16:03:28 +1000 Subject: [PATCH] Android: Allow opening/getting files relative to downloads directory --- .../stenzek/duckstation/FileHelper.java | 110 +++++++++++++++ src/common/cd_image.cpp | 36 +++-- src/common/cd_image_bin.cpp | 2 +- src/common/cd_image_chd.cpp | 2 +- src/common/cd_image_cue.cpp | 2 +- src/common/cd_image_ecm.cpp | 2 +- src/common/cd_image_mds.cpp | 2 +- src/common/cd_image_pbp.cpp | 4 +- src/common/cd_subchannel_replacement.cpp | 5 + src/common/cd_subchannel_replacement.h | 1 + src/common/file_system.cpp | 129 +++++++++++++++++- src/common/file_system.h | 6 +- src/core/host_interface.cpp | 6 +- src/frontend-common/common_host_interface.cpp | 2 +- src/frontend-common/fullscreen_ui.cpp | 8 +- src/frontend-common/game_list.cpp | 5 +- 16 files changed, 281 insertions(+), 41 deletions(-) diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/FileHelper.java b/android/app/src/main/java/com/github/stenzek/duckstation/FileHelper.java index 006e9601e..703bb4b78 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/FileHelper.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/FileHelper.java @@ -20,6 +20,7 @@ import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.List; /** * File helper class - used to bridge native code to Java storage access framework APIs. @@ -53,6 +54,21 @@ public class FileHelper { DocumentsContract.Document.COLUMN_LAST_MODIFIED }; + /** + * Projection used when getting the display name for a file. + */ + private static final String[] getDisplayNameProjection = new String[]{ + DocumentsContract.Document.COLUMN_DISPLAY_NAME, + }; + + /** + * Projection used when getting a relative file for a file. + */ + private static final String[] getRelativeFileProjection = new String[]{ + DocumentsContract.Document.COLUMN_DOCUMENT_ID, + DocumentsContract.Document.COLUMN_DISPLAY_NAME, + }; + private final Context context; private final ContentResolver contentResolver; @@ -244,6 +260,7 @@ public class FileHelper { /** * Returns the file name component of a path or URI. + * * @param path Path/URI to examine. * @return File name component of path/URI. */ @@ -265,6 +282,14 @@ public class FileHelper { return path; } + /** + * Test if the given URI represents a {@link DocumentsContract.Document} tree. + */ + public static boolean isTreeUri(Uri uri) { + final List paths = uri.getPathSegments(); + return (paths.size() >= 2 && paths.get(0).equals("tree")); + } + /** * Retrieves a file descriptor for a content URI string. Called by native code. * @@ -353,6 +378,91 @@ public class FileHelper { } } + /** + * Returns the display name for the given URI. + * + * @param uriString URI to resolve display name for. + * @return display name for the URI, or null. + */ + public String getDisplayNameForURIPath(String uriString) { + try { + final Uri fullUri = Uri.parse(uriString); + final Cursor cursor = contentResolver.query(fullUri, getDisplayNameProjection, + null, null, null); + if (cursor.getCount() == 0 || !cursor.moveToNext()) + return null; + + return cursor.getString(0); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * Returns the path for a sibling file relative to another URI. + * + * @param uriString URI to find the file relative to. + * @param newFileName Sibling file name. + * @return URI for the sibling file name, or null. + */ + public String getRelativePathForURIPath(String uriString, String newFileName) { + try { + final Uri fullUri = Uri.parse(uriString); + + // if this is a document (expected)... + Uri treeUri; + String treeDocId; + if (DocumentsContract.isDocumentUri(context, fullUri)) { + // we need to remove the last part of the URI (the specific document ID) to get the parent + final String lastPathSegment = fullUri.getLastPathSegment(); + int lastSeparatorIndex = lastPathSegment.lastIndexOf('/'); + if (lastSeparatorIndex < 0) + lastSeparatorIndex = lastPathSegment.lastIndexOf(':'); + if (lastSeparatorIndex < 0) + return null; + + // the parent becomes the document ID + treeDocId = lastPathSegment.substring(0, lastSeparatorIndex); + + // but, we need to access it through the subtree if this was a tree URI (permissions...) + if (isTreeUri(fullUri)) { + treeUri = DocumentsContract.buildTreeDocumentUri(fullUri.getAuthority(), DocumentsContract.getTreeDocumentId(fullUri)); + } else { + treeUri = DocumentsContract.buildTreeDocumentUri(fullUri.getAuthority(), treeDocId); + } + } else { + treeDocId = DocumentsContract.getDocumentId(fullUri); + treeUri = fullUri; + } + + final Uri queryUri = DocumentsContract.buildChildDocumentsUriUsingTree(treeUri, treeDocId); + final Cursor cursor = contentResolver.query(queryUri, getRelativeFileProjection, null, null, null); + final int count = cursor.getCount(); + + while (cursor.moveToNext()) { + try { + final String displayName = cursor.getString(1); + if (!displayName.equalsIgnoreCase(newFileName)) + continue; + + final String childDocumentId = cursor.getString(0); + final Uri uri = DocumentsContract.buildDocumentUriUsingTree(treeUri, childDocumentId); + cursor.close(); + return uri.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + cursor.close(); + return null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /** * Java class containing the data for a file in a find operation. */ diff --git a/src/common/cd_image.cpp b/src/common/cd_image.cpp index 915f607e0..020024bf4 100644 --- a/src/common/cd_image.cpp +++ b/src/common/cd_image.cpp @@ -2,6 +2,7 @@ #include "assert.h" #include "file_system.h" #include "log.h" +#include "string_util.h" #include Log_SetChannel(CDImage); @@ -17,45 +18,50 @@ u32 CDImage::GetBytesPerSector(TrackMode mode) std::unique_ptr CDImage::Open(const char* filename, Common::Error* error) { - const char* extension = std::strrchr(filename, '.'); + const char* extension; + +#ifdef __ANDROID__ + std::string filename_display_name(FileSystem::GetDisplayNameFromPath(filename)); + if (filename_display_name.empty()) + filename_display_name = filename; + + extension = std::strrchr(filename_display_name.c_str(), '.'); +#else + extension = std::strrchr(filename, '.'); +#endif + if (!extension) { Log_ErrorPrintf("Invalid filename: '%s'", filename); return nullptr; } -#ifdef _MSC_VER -#define CASE_COMPARE _stricmp -#else -#define CASE_COMPARE strcasecmp -#endif - - if (CASE_COMPARE(extension, ".cue") == 0) + if (StringUtil::Strcasecmp(extension, ".cue") == 0) { return OpenCueSheetImage(filename, error); } - else if (CASE_COMPARE(extension, ".bin") == 0 || CASE_COMPARE(extension, ".img") == 0 || - CASE_COMPARE(extension, ".iso") == 0) + else if (StringUtil::Strcasecmp(extension, ".bin") == 0 || StringUtil::Strcasecmp(extension, ".img") == 0 || + StringUtil::Strcasecmp(extension, ".iso") == 0) { return OpenBinImage(filename, error); } - else if (CASE_COMPARE(extension, ".chd") == 0) + else if (StringUtil::Strcasecmp(extension, ".chd") == 0) { return OpenCHDImage(filename, error); } - else if (CASE_COMPARE(extension, ".ecm") == 0) + else if (StringUtil::Strcasecmp(extension, ".ecm") == 0) { return OpenEcmImage(filename, error); } - else if (CASE_COMPARE(extension, ".mds") == 0) + else if (StringUtil::Strcasecmp(extension, ".mds") == 0) { return OpenMdsImage(filename, error); } - else if (CASE_COMPARE(extension, ".pbp") == 0) + else if (StringUtil::Strcasecmp(extension, ".pbp") == 0) { return OpenPBPImage(filename, error); } - else if (CASE_COMPARE(extension, ".m3u") == 0) + else if (StringUtil::Strcasecmp(extension, ".m3u") == 0) { return OpenM3uImage(filename, error); } diff --git a/src/common/cd_image_bin.cpp b/src/common/cd_image_bin.cpp index b94f34667..b364348cb 100644 --- a/src/common/cd_image_bin.cpp +++ b/src/common/cd_image_bin.cpp @@ -94,7 +94,7 @@ bool CDImageBin::Open(const char* filename, Common::Error* error) AddLeadOutIndex(); - m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str()); + m_sbi.LoadSBIFromImagePath(filename); return Seek(1, Position{0, 0, 0}); } diff --git a/src/common/cd_image_chd.cpp b/src/common/cd_image_chd.cpp index a2b7d6d09..eccb2744b 100644 --- a/src/common/cd_image_chd.cpp +++ b/src/common/cd_image_chd.cpp @@ -279,7 +279,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) m_lba_count = disc_lba; AddLeadOutIndex(); - m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str()); + m_sbi.LoadSBIFromImagePath(filename); return Seek(1, Position{0, 0, 0}); } diff --git a/src/common/cd_image_cue.cpp b/src/common/cd_image_cue.cpp index 2e71b0c06..9a2d64fee 100644 --- a/src/common/cd_image_cue.cpp +++ b/src/common/cd_image_cue.cpp @@ -269,7 +269,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) m_lba_count = disc_lba; AddLeadOutIndex(); - m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str()); + m_sbi.LoadSBIFromImagePath(filename); return Seek(1, Position{0, 0, 0}); } diff --git a/src/common/cd_image_ecm.cpp b/src/common/cd_image_ecm.cpp index 85222e2d1..999fc7973 100644 --- a/src/common/cd_image_ecm.cpp +++ b/src/common/cd_image_ecm.cpp @@ -385,7 +385,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) AddLeadOutIndex(); - m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str()); + m_sbi.LoadSBIFromImagePath(filename); m_chunk_buffer.reserve(RAW_SECTOR_SIZE * 2); return Seek(1, Position{0, 0, 0}); diff --git a/src/common/cd_image_mds.cpp b/src/common/cd_image_mds.cpp index ccb3b71c8..bfb73ff11 100644 --- a/src/common/cd_image_mds.cpp +++ b/src/common/cd_image_mds.cpp @@ -250,7 +250,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) m_lba_count = m_tracks.back().start_lba + m_tracks.back().length; AddLeadOutIndex(); - m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str()); + m_sbi.LoadSBIFromImagePath(filename); return Seek(1, Position{0, 0, 0}); } diff --git a/src/common/cd_image_pbp.cpp b/src/common/cd_image_pbp.cpp index 7fc4b4da9..0fc083494 100644 --- a/src/common/cd_image_pbp.cpp +++ b/src/common/cd_image_pbp.cpp @@ -673,8 +673,8 @@ bool CDImagePBP::OpenDisc(u32 index, Common::Error* error) if (m_disc_offsets.size() > 1) { - std::string sbi_path = - FileSystem::StripExtension(m_filename) + StringUtil::StdStringFromFormat("_%u.sbi", index + 1); + std::string sbi_path(FileSystem::StripExtension(m_filename)); + sbi_path += TinyString::FromFormat("_%u.sbi", index + 1); m_sbi.LoadSBI(sbi_path.c_str()); } else diff --git a/src/common/cd_subchannel_replacement.cpp b/src/common/cd_subchannel_replacement.cpp index 76b4ffafa..0a7915288 100644 --- a/src/common/cd_subchannel_replacement.cpp +++ b/src/common/cd_subchannel_replacement.cpp @@ -83,6 +83,11 @@ bool CDSubChannelReplacement::LoadSBI(const char* path) return true; } +bool CDSubChannelReplacement::LoadSBIFromImagePath(const char* image_path) +{ + return LoadSBI(FileSystem::ReplaceExtension(image_path, "sbi").c_str()); +} + void CDSubChannelReplacement::AddReplacementSubChannelQ(u32 lba, const CDImage::SubChannelQ& subq) { auto iter = m_replacement_subq.find(lba); diff --git a/src/common/cd_subchannel_replacement.h b/src/common/cd_subchannel_replacement.h index 4c622dfa2..6bdda6e1a 100644 --- a/src/common/cd_subchannel_replacement.h +++ b/src/common/cd_subchannel_replacement.h @@ -14,6 +14,7 @@ public: u32 GetReplacementSectorCount() const { return static_cast(m_replacement_subq.size()); } bool LoadSBI(const char* path); + bool LoadSBIFromImagePath(const char* image_path); /// Adds a sector to the replacement map. void AddReplacementSubChannelQ(u32 lba, const CDImage::SubChannelQ& subq); diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index 3a0072257..a3ee5e19b 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -51,6 +51,8 @@ static jfieldID s_android_FileHelper_FindResult_relativeName; static jfieldID s_android_FileHelper_FindResult_size; static jfieldID s_android_FileHelper_FindResult_modifiedTime; static jfieldID s_android_FileHelper_FindResult_flags; +static jmethodID s_android_FileHelper_getDisplayName; +static jmethodID s_android_FileHelper_getRelativePathForURIPath; // helper for retrieving the current per-thread jni environment static JNIEnv* GetJNIEnv() @@ -89,6 +91,8 @@ void SetAndroidFileHelper(void* jvm, void* env, void* object) jenv->DeleteGlobalRef(s_android_FileHelper_object); jenv->DeleteGlobalRef(s_android_FileHelper_class); + s_android_FileHelper_getRelativePathForURIPath = {}; + s_android_FileHelper_getDisplayName = {}; s_android_FileHelper_openURIAsFileDescriptor = {}; s_android_FileHelper_FindFiles = {}; s_android_FileHelper_object = {}; @@ -114,7 +118,13 @@ void SetAndroidFileHelper(void* jvm, void* env, void* object) s_android_FileHelper_FindFiles = jenv->GetMethodID(s_android_FileHelper_class, "findFiles", "(Ljava/lang/String;I)[Lcom/github/stenzek/duckstation/FileHelper$FindResult;"); - Assert(s_android_FileHelper_openURIAsFileDescriptor && s_android_FileHelper_FindFiles); + s_android_FileHelper_getDisplayName = + jenv->GetMethodID(s_android_FileHelper_class, "getDisplayNameForURIPath", "(Ljava/lang/String;)Ljava/lang/String;"); + s_android_FileHelper_getRelativePathForURIPath = + jenv->GetMethodID(s_android_FileHelper_class, "getRelativePathForURIPath", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + Assert(s_android_FileHelper_openURIAsFileDescriptor && s_android_FileHelper_FindFiles && + s_android_FileHelper_getDisplayName && s_android_FileHelper_getRelativePathForURIPath); jclass fr_class = jenv->FindClass("com/github/stenzek/duckstation/FileHelper$FindResult"); Assert(fr_class); @@ -279,6 +289,68 @@ static bool FindUriFiles(const char* path, const char* pattern, u32 flags, FindR return true; } +static bool GetDisplayNameForUriPath(const char* path, std::string* result) +{ + if (!s_android_FileHelper_object) + return false; + + JNIEnv* env = GetJNIEnv(); + + jstring path_jstr = env->NewStringUTF(path); + jstring result_jstr = static_cast( + env->CallObjectMethod(s_android_FileHelper_object, s_android_FileHelper_getDisplayName, path_jstr)); + env->DeleteLocalRef(path_jstr); + if (!result_jstr) + return false; + + const char* result_name = env->GetStringUTFChars(result_jstr, nullptr); + if (result_name) + { + Log_DevPrintf("GetDisplayNameForUriPath(\"%s\") -> \"%s\"", path, result_name); + result->assign(result_name); + } + else + { + result->clear(); + } + + env->ReleaseStringUTFChars(result_jstr, result_name); + env->DeleteLocalRef(result_jstr); + return true; +} + +static bool GetRelativePathForUriPath(const char* path, const char* filename, std::string* result) +{ + if (!s_android_FileHelper_object) + return false; + + JNIEnv* env = GetJNIEnv(); + + jstring path_jstr = env->NewStringUTF(path); + jstring filename_jstr = env->NewStringUTF(filename); + jstring result_jstr = static_cast(env->CallObjectMethod( + s_android_FileHelper_object, s_android_FileHelper_getRelativePathForURIPath, path_jstr, filename_jstr)); + env->DeleteLocalRef(filename_jstr); + env->DeleteLocalRef(path_jstr); + if (!result_jstr) + return false; + + const char* result_name = env->GetStringUTFChars(result_jstr, nullptr); + if (result_name) + { + Log_DevPrintf("GetRelativePathForUriPath(\"%s\", \"%s\") -> \"%s\"", path, filename, result_name); + result->assign(result_name); + } + else + { + result->clear(); + } + + env->ReleaseStringUTFChars(result_jstr, result_name); + env->DeleteLocalRef(result_jstr); + return true; +} + #endif // __ANDROID__ ChangeNotifier::ChangeNotifier(const String& directoryPath, bool recursiveWatch) @@ -510,17 +582,33 @@ bool IsAbsolutePath(const std::string_view& path) #endif } -std::string StripExtension(const std::string_view& path) +std::string_view StripExtension(const std::string_view& path) { std::string_view::size_type pos = path.rfind('.'); if (pos == std::string::npos) - return std::string(path); + return path; - return std::string(path, 0, pos); + return path.substr(0, pos); } std::string ReplaceExtension(const std::string_view& path, const std::string_view& new_extension) { +#ifdef __ANDROID__ + // This is more complex on android because the path may not contain the actual filename. + if (IsUriPath(path)) + { + std::string display_name(GetDisplayNameFromPath(path)); + std::string_view::size_type pos = display_name.rfind('.'); + if (pos == std::string::npos) + return std::string(path); + + display_name.erase(pos + 1); + display_name.append(new_extension); + + return BuildRelativePath(path, display_name); + } +#endif + std::string_view::size_type pos = path.rfind('.'); if (pos == std::string::npos) return std::string(path); @@ -572,6 +660,28 @@ static std::string_view::size_type GetLastSeperatorPosition(const std::string_vi return last_separator; } +std::string GetDisplayNameFromPath(const std::string_view& path) +{ +#if defined(__ANDROID__) + std::string result; + + if (IsUriPath(path)) + { + std::string temp(path); + if (!GetDisplayNameForUriPath(temp.c_str(), &result)) + result = std::move(temp); + } + else + { + result = path; + } + + return result; +#else + return std::string(GetFileNameFromPath(path)); +#endif +} + std::string_view GetPathDirectory(const std::string_view& path) { std::string::size_type pos = GetLastSeperatorPosition(path, false); @@ -583,7 +693,7 @@ std::string_view GetPathDirectory(const std::string_view& path) std::string_view GetFileNameFromPath(const std::string_view& path) { - std::string::size_type pos = GetLastSeperatorPosition(path, true); + std::string_view::size_type pos = GetLastSeperatorPosition(path, true); if (pos == std::string_view::npos) return path; @@ -630,6 +740,15 @@ std::vector GetRootDirectoryList() std::string BuildRelativePath(const std::string_view& filename, const std::string_view& new_filename) { std::string new_string; + +#ifdef __ANDROID__ + if (IsUriPath(filename) && + GetRelativePathForUriPath(std::string(filename).c_str(), std::string(new_filename).c_str(), &new_string)) + { + return new_string; + } +#endif + std::string_view::size_type pos = GetLastSeperatorPosition(filename, true); if (pos != std::string_view::npos) new_string.assign(filename, 0, pos); diff --git a/src/common/file_system.h b/src/common/file_system.h index b7217dbf8..5117e79fd 100644 --- a/src/common/file_system.h +++ b/src/common/file_system.h @@ -145,11 +145,15 @@ void SanitizeFileName(std::string& Destination, bool StripSlashes = true); bool IsAbsolutePath(const std::string_view& path); /// Removes the extension of a filename. -std::string StripExtension(const std::string_view& path); +std::string_view StripExtension(const std::string_view& path); /// Replaces the extension of a filename with another. std::string ReplaceExtension(const std::string_view& path, const std::string_view& new_extension); +/// Returns the display name of a filename. Usually this is the same as the path, except on Android +/// where it resolves a content URI to its name. +std::string GetDisplayNameFromPath(const std::string_view& path); + /// Returns the directory component of a filename. std::string_view GetPathDirectory(const std::string_view& path); diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index da4198ab8..78095a2d9 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -33,8 +33,7 @@ HostInterface::HostInterface() g_host_interface = this; // we can get the program directory at construction time - const std::string program_path = FileSystem::GetProgramPath(); - m_program_directory = FileSystem::GetPathDirectory(program_path.c_str()); + m_program_directory = FileSystem::GetPathDirectory(FileSystem::GetProgramPath()); } HostInterface::~HostInterface() @@ -896,8 +895,7 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings) void HostInterface::SetUserDirectoryToProgramDirectory() { - const std::string program_path(FileSystem::GetProgramPath()); - const std::string program_directory(FileSystem::GetPathDirectory(program_path.c_str())); + const std::string program_directory(FileSystem::GetProgramPath()); m_user_directory = program_directory; } diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index adb6eef68..bb1775e9d 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -2914,7 +2914,7 @@ void CommonHostInterface::GetGameInfo(const char* path, CDImage* image, std::str } else { - *title = FileSystem::GetFileTitleFromPath(path); + *title = FileSystem::GetFileTitleFromPath(std::string(path)); if (image) *code = System::GetGameCodeForImage(image, true); } diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 6745bdf14..e5986f92e 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -662,7 +662,7 @@ static void DoChangeDiscFromFile() }; OpenFileSelector(ICON_FA_COMPACT_DISC " Select Disc Image", false, std::move(callback), GetDiscImageFilters(), - std::string(FileSystem::GetPathDirectory(System::GetMediaFileName().c_str()))); + std::string(FileSystem::GetPathDirectory(System::GetMediaFileName()))); } static void DoChangeDisc() @@ -1076,7 +1076,7 @@ static bool SettingInfoButton(const SettingInfo& si, const char* section) CloseFileSelector(); }; OpenFileSelector(si.visible_name, false, std::move(callback), ImGuiFullscreen::FileSelectorFilters(), - std::string(FileSystem::GetPathDirectory(value.c_str()))); + std::string(FileSystem::GetPathDirectory(std::move(value)))); } return false; @@ -2372,7 +2372,7 @@ void DrawQuickMenu(MainWindowType type) SmallString subtitle; if (!code.empty()) subtitle.Format("%s - ", code.c_str()); - subtitle.AppendString(FileSystem::GetFileNameFromPath(System::GetRunningPath().c_str())); + subtitle.AppendString(FileSystem::GetFileNameFromPath(System::GetRunningPath())); const ImVec2 title_size( g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits::max(), -1.0f, title.c_str())); @@ -2805,7 +2805,7 @@ void DrawGameListWindow() else summary.Format("%s - %s - ", entry->code.c_str(), Settings::GetDiscRegionName(entry->region)); - summary.AppendString(FileSystem::GetFileNameFromPath(entry->path.c_str())); + summary.AppendString(FileSystem::GetFileNameFromPath(entry->path)); ImGui::GetWindowDrawList()->AddImage(cover_texture->GetHandle(), bb.Min, bb.Min + image_size, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255)); diff --git a/src/frontend-common/game_list.cpp b/src/frontend-common/game_list.cpp index 89da363a1..a199bded1 100644 --- a/src/frontend-common/game_list.cpp +++ b/src/frontend-common/game_list.cpp @@ -487,11 +487,8 @@ void GameList::ScanDirectory(const char* path, bool recursive, ProgressCallback* if (AddFileFromCache(ffd.FileName, modified_time)) continue; - const std::string_view file_part(FileSystem::GetFileNameFromPath(ffd.FileName)); - if (!file_part.empty()) - progress->SetFormattedStatusText("Scanning '%*s'...", static_cast(file_part.size()), file_part.data()); - // ownership of fp is transferred + progress->SetFormattedStatusText("Scanning '%s'...", FileSystem::GetDisplayNameFromPath(ffd.FileName).c_str()); ScanFile(std::move(ffd.FileName), modified_time); }