Fix Flatpak user path

This commit is contained in:
Pengfei
2021-07-13 21:55:35 +08:00
parent d002928a38
commit e41151420f
5 changed files with 77 additions and 26 deletions
+1
View File
@@ -23,6 +23,7 @@
#define EMU_DATA_DIR "citra-emu" #define EMU_DATA_DIR "citra-emu"
#endif #endif
#endif #endif
#define CITRA_EXECUTABLE "citra-qt"
// Subdirs in the User dir returned by GetUserPath(UserPath::UserDir) // Subdirs in the User dir returned by GetUserPath(UserPath::UserDir)
#define CONFIG_DIR "config" #define CONFIG_DIR "config"
+48 -16
View File
@@ -694,9 +694,36 @@ std::string GetSysDirectory() {
namespace { namespace {
std::unordered_map<UserPath, std::string> g_paths; std::unordered_map<UserPath, std::string> g_paths;
bool g_portable_user_directory = false;
} // namespace } // namespace
UserPathType GetUserPathType() {
#ifdef _WIN32
const auto user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
if (FileUtil::Exists(user_path)) {
return UserPathType::Portable;
} else {
return UserPathType::Normal;
}
#elif ANDROID
UNREACHABLE_MSG("Android is not supported (yet)");
#else
if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP)) {
return UserPathType::Portable;
} else if (FileUtil::Exists(ROOT_DIR DIR_SEP CITRA_EXECUTABLE)) {
return UserPathType::Normal;
}
const bool normal_exists =
FileUtil::Exists(GetUserDirectory("XDG_DATA_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP);
const bool flatpak_exists = FileUtil::Exists(
GetHomeDirectory() + "/.var/app/org.citra_emu.citra/data" + DIR_SEP EMU_DATA_DIR DIR_SEP);
if (!normal_exists || flatpak_exists) { // Flatpak takes precedence
return UserPathType::Flatpak;
}
return UserPathType::Normal;
#endif
}
void SetUserPath(const std::string& path) { void SetUserPath(const std::string& path) {
if (!g_paths.empty()) { if (!g_paths.empty()) {
g_paths.clear(); g_paths.clear();
@@ -711,27 +738,26 @@ void SetUserPath(const std::string& path) {
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
} else { } else {
#ifdef _WIN32 #ifdef _WIN32
user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; if (GetUserPathType() == UserPathType::Portable) {
if (!FileUtil::IsDirectory(user_path)) {
user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
} else {
LOG_INFO(Common_Filesystem, "Using the local user directory"); LOG_INFO(Common_Filesystem, "Using the local user directory");
g_portable_user_directory = true; user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
} else {
user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
} }
g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
#elif ANDROID #elif ANDROID
ASSERT_MSG(false, "Specified path {} is not valid", path); UNREACHABLE_MSG("Android is not supported (yet)");
#else #else
if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { switch (GetUserPathType()) {
case UserPathType::Portable: {
user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
break;
LOG_INFO(Common_Filesystem, "Using the local user directory"); }
g_portable_user_directory = true; case UserPathType::Normal: {
} else {
std::string data_dir = GetUserDirectory("XDG_DATA_HOME"); std::string data_dir = GetUserDirectory("XDG_DATA_HOME");
std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME"); std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME");
std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME"); std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME");
@@ -739,6 +765,16 @@ void SetUserPath(const std::string& path) {
user_path = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; user_path = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
g_paths.emplace(UserPath::ConfigDir, config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); g_paths.emplace(UserPath::ConfigDir, config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP);
g_paths.emplace(UserPath::CacheDir, cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); g_paths.emplace(UserPath::CacheDir, cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP);
break;
}
case UserPathType::Flatpak: {
const auto base_path = GetHomeDirectory() + "/.var/app/org.citra_emu.citra/";
user_path = base_path + "data/citra-emu/";
g_paths.emplace(UserPath::ConfigDir, base_path + "config/citra-emu/");
g_paths.emplace(UserPath::CacheDir, base_path + "cache/citra-emu/");
break;
}
} }
#endif #endif
} }
@@ -758,10 +794,6 @@ const std::string& GetUserPath(UserPath path) {
return g_paths[path]; return g_paths[path];
} }
bool IsPortableUserDirectory() {
return g_portable_user_directory;
}
std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str) { std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str) {
return IOFile(filename, text_file ? "w" : "wb").WriteString(str); return IOFile(filename, text_file ? "w" : "wb").WriteString(str);
} }
+9 -3
View File
@@ -129,6 +129,15 @@ void CopyDir(const std::string& source_path, const std::string& dest_path);
// Set the current directory to given directory // Set the current directory to given directory
bool SetCurrentDir(const std::string& directory); bool SetCurrentDir(const std::string& directory);
enum class UserPathType {
Normal, /// user-wide normal install
Portable, /// portable install
Flatpak, /// Flatpak install (Linux only)
};
// Determine type of the user path that should be used.
UserPathType GetUserPathType();
// User paths are not directly used by us, and are only preserved here to match Citra's // User paths are not directly used by us, and are only preserved here to match Citra's
// user folder and tell where to copy the files to. // user folder and tell where to copy the files to.
@@ -138,9 +147,6 @@ void SetUserPath(const std::string& path = "");
// directory. To be used in "multi-user" mode (that is, installed). // directory. To be used in "multi-user" mode (that is, installed).
const std::string& GetUserPath(UserPath path); const std::string& GetUserPath(UserPath path);
// Whetehr we are using the portable user directory.
bool IsPortableUserDirectory();
// Returns the path to where the sys file are // Returns the path to where the sys file are
std::string GetSysDirectory(); std::string GetSysDirectory();
+2 -3
View File
@@ -256,9 +256,8 @@ void ImportDialog::InsertSecondLevelItem(std::size_t row, const Core::ContentSpe
encryption.clear(); encryption.clear();
} }
auto* item = new QTreeWidgetItem{ auto* item = new QTreeWidgetItem{{QString{}, name, ReadableByteSize(content.maximum_size),
{QString{}, name, ReadableByteSize(content.maximum_size), encryption, encryption, content.already_exists ? tr("Yes") : tr("No")}};
content.already_exists ? QStringLiteral("Yes") : QStringLiteral("No")}};
QPixmap icon; QPixmap icon;
if (replace_icon.isNull()) { if (replace_icon.isNull()) {
+17 -4
View File
@@ -11,6 +11,7 @@
#include <QStorageInfo> #include <QStorageInfo>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include <qdevicewatcher.h> #include <qdevicewatcher.h>
#include "common/assert.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "frontend/import_dialog.h" #include "frontend/import_dialog.h"
#include "frontend/main.h" #include "frontend/main.h"
@@ -60,10 +61,22 @@ MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<U
} }
}); });
ui->importDestination->setText(tr("Import Destination: %1") QString destination_text{};
.arg(FileUtil::IsPortableUserDirectory() const auto destination = FileUtil::GetUserPathType();
? tr("Portable Citra Install") if (destination == FileUtil::UserPathType::Normal) {
: tr("User-wide Citra Install"))); #ifdef __linux__
destination_text = tr("Non-Flatpak Citra Install");
#else
destination_text = tr("User-wide Citra Install");
#endif
} else if (destination == FileUtil::UserPathType::Portable) {
destination_text = tr("Portable Citra Install");
} else if (destination == FileUtil::UserPathType::Flatpak) {
destination_text = tr("Flatpak Citra Install");
} else {
UNREACHABLE();
}
ui->importDestination->setText(tr("Import Destination: %1").arg(destination_text));
connect(ui->main, &QTreeWidget::itemSelectionChanged, [this] { connect(ui->main, &QTreeWidget::itemSelectionChanged, [this] {
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok) ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)