From ceef556e3ee87ba6bf83982d807ef53cc8eab5c0 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Wed, 4 Dec 2024 03:09:28 +0700 Subject: [PATCH] Implements data root reading for Linux (#1158) --- Cargo.lock | 7 ++++ gui/Cargo.toml | 3 ++ gui/initialize_wizard.cpp | 87 --------------------------------------- gui/src/setup/data.rs | 17 -------- gui/src/setup/linux.rs | 34 +++++++++++++++ gui/src/setup/macos.rs | 10 +++++ gui/src/setup/mod.rs | 10 ++++- gui/src/setup/windows.rs | 10 +++++ 8 files changed, 73 insertions(+), 105 deletions(-) delete mode 100644 gui/src/setup/data.rs create mode 100644 gui/src/setup/linux.rs create mode 100644 gui/src/setup/macos.rs create mode 100644 gui/src/setup/windows.rs diff --git a/Cargo.lock b/Cargo.lock index 5cfa0bafb..d7da88e42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1592,6 +1592,7 @@ dependencies = [ "windows-sys 0.52.0", "winres", "x86-64", + "xdg", ] [[package]] @@ -4800,6 +4801,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" +[[package]] +name = "xdg" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" + [[package]] name = "xdg-home" version = "1.3.0" diff --git a/gui/Cargo.toml b/gui/Cargo.toml index e95ac2a3e..31a16aa24 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -66,6 +66,9 @@ version = "0.10.2" features = ["async-std", "raw_handle"] default-features = false +[target.'cfg(target_os = "linux")'.dependencies] +xdg = "2.5.2" + [target.'cfg(target_os = "macos")'.dependencies] applevisor-sys = "0.1.3" core-graphics-types = "0.1.3" diff --git a/gui/initialize_wizard.cpp b/gui/initialize_wizard.cpp index 0976716be..e8ec33592 100644 --- a/gui/initialize_wizard.cpp +++ b/gui/initialize_wizard.cpp @@ -16,86 +16,11 @@ #define FIELD_GAMES_LOCATION "gamesLocation" enum PageId { - PageSystem, PageGame, PageFirmware, PageConclusion }; -class SystemPage : public QWizardPage { -public: - SystemPage() : m_input(nullptr) - { - auto layout = new QVBoxLayout(); - - // Page properties. - setTitle("Location for system files"); - setSubTitle( - "The selected directory will be used for everything except games (e.g. save " - "data and firmware files)."); - - // Widgets. - layout->addLayout(setupInputRow()); - - setLayout(layout); - } - - bool validatePage() override - { - auto path = m_input->text(); - - if (!QDir::isAbsolutePath(path)) { - QMessageBox::critical(this, "Error", "The location must be an absolute path."); - return false; - } - - if (!QDir(path).exists()) { - QMessageBox::critical(this, "Error", "The location does not exist."); - return false; - } - - return true; - } -private: - QLayout *setupInputRow() - { - auto layout = new QHBoxLayout(); - - // Label. - auto label = new QLabel("&Location:"); - layout->addWidget(label); - - // Input. - m_input = new QLineEdit(); - m_input->setText(readSystemDirectorySetting()); - - label->setBuddy(m_input); - layout->addWidget(m_input); - - registerField(FIELD_SYSTEM_LOCATION "*", m_input); - - // Browse. - auto browse = new QPushButton("..."); - - connect(browse, &QPushButton::clicked, this, &SystemPage::browseDirectory); - - layout->addWidget(browse); - - return layout; - } - - void browseDirectory() - { - auto path = QFileDialog::getExistingDirectory(this, "Location for system files"); - - if (!path.isEmpty()) { - m_input->setText(QDir::toNativeSeparators(path)); - } - } - - QLineEdit *m_input; -}; - class GamePage : public QWizardPage { public: GamePage() : m_input(nullptr) @@ -247,11 +172,6 @@ class ConclusionPage : public QWizardPage { { auto wizard = this->wizard(); - if (wizard->hasVisitedPage(PageSystem)) { - auto path = field(FIELD_SYSTEM_LOCATION).toString(); - writeSystemDirectorySetting(QDir::toNativeSeparators(path)); - } - if (wizard->hasVisitedPage(PageGame)) { auto path = field(FIELD_GAMES_LOCATION).toString(); writeGamesDirectorySetting(QDir::toNativeSeparators(path)); @@ -272,7 +192,6 @@ InitializeWizard::InitializeWizard() #endif // Pages. - setPage(PageSystem, new SystemPage()); setPage(PageGame, new GamePage()); setPage(PageFirmware, new FirmwarePage()); setPage(PageConclusion, new ConclusionPage()); @@ -285,12 +204,6 @@ InitializeWizard::~InitializeWizard() int InitializeWizard::nextId() const { switch (currentId()) { - case PageSystem: - if (!hasGamesDirectorySetting()) { - return PageGame; - } - - [[fallthrough]]; case PageGame: return PageFirmware; case PageFirmware: diff --git a/gui/src/setup/data.rs b/gui/src/setup/data.rs deleted file mode 100644 index 8630e7f74..000000000 --- a/gui/src/setup/data.rs +++ /dev/null @@ -1,17 +0,0 @@ -use super::SetupError; -use std::path::PathBuf; - -#[cfg(target_os = "linux")] -pub fn read_data_root() -> Result, SetupError> { - todo!() -} - -#[cfg(target_os = "macos")] -pub fn read_data_root() -> Result, SetupError> { - todo!() -} - -#[cfg(target_os = "windows")] -pub fn read_data_root() -> Result, SetupError> { - todo!() -} diff --git a/gui/src/setup/linux.rs b/gui/src/setup/linux.rs new file mode 100644 index 000000000..25e0a7aed --- /dev/null +++ b/gui/src/setup/linux.rs @@ -0,0 +1,34 @@ +use std::io::ErrorKind; +use std::path::PathBuf; +use thiserror::Error; +use xdg::BaseDirectories; + +pub fn read_data_root() -> Result, DataRootError> { + let file = get_config_path()?; + + match std::fs::read_to_string(&file) { + Ok(v) => Ok(Some(v.trim().into())), + Err(e) if e.kind() == ErrorKind::NotFound => Ok(None), + Err(e) => Err(DataRootError::ReadFile(file, e)), + } +} + +fn get_config_path() -> Result { + BaseDirectories::new() + .map(|xdg| { + let mut p = xdg.get_config_home(); + p.push("obliteration.conf"); + p + }) + .map_err(DataRootError::XdgBaseDirectory) +} + +/// Represents an error when read or write data root fails. +#[derive(Debug, Error)] +pub enum DataRootError { + #[error("couldn't load XDG Base Directory")] + XdgBaseDirectory(#[source] xdg::BaseDirectoriesError), + + #[error("couldn't read {0}")] + ReadFile(PathBuf, #[source] std::io::Error), +} diff --git a/gui/src/setup/macos.rs b/gui/src/setup/macos.rs new file mode 100644 index 000000000..85fd200bf --- /dev/null +++ b/gui/src/setup/macos.rs @@ -0,0 +1,10 @@ +use std::path::PathBuf; +use thiserror::Error; + +pub fn read_data_root() -> Result, DataRootError> { + todo!() +} + +/// Represents an error when read or write data root fails. +#[derive(Debug, Error)] +pub enum DataRootError {} diff --git a/gui/src/setup/mod.rs b/gui/src/setup/mod.rs index 1b837149c..2637d7ed9 100644 --- a/gui/src/setup/mod.rs +++ b/gui/src/setup/mod.rs @@ -1,3 +1,5 @@ +pub use self::data::DataRootError; + use self::data::read_data_root; use crate::data::{DataError, DataMgr}; use crate::dialogs::{open_file, FileType}; @@ -12,11 +14,14 @@ use std::path::PathBuf; use std::rc::Rc; use thiserror::Error; +#[cfg_attr(target_os = "linux", path = "linux.rs")] +#[cfg_attr(target_os = "macos", path = "macos.rs")] +#[cfg_attr(target_os = "windows", path = "windows.rs")] mod data; pub fn run_setup() -> Result, SetupError> { // Load data root. - let root = read_data_root()?; + let root = read_data_root().map_err(SetupError::ReadDataRoot)?; if let Some(p) = root.as_ref().filter(|p| p.is_dir()) { // Check if root partition exists. @@ -115,6 +120,9 @@ fn install_firmware(win: SetupWizard) { /// Represents an error when [`run_setup()`] fails. #[derive(Debug, Error)] pub enum SetupError { + #[error("couldn't read data location")] + ReadDataRoot(#[source] DataRootError), + #[error("couldn't create data manager on {0}")] DataManager(PathBuf, #[source] DataError), diff --git a/gui/src/setup/windows.rs b/gui/src/setup/windows.rs new file mode 100644 index 000000000..85fd200bf --- /dev/null +++ b/gui/src/setup/windows.rs @@ -0,0 +1,10 @@ +use std::path::PathBuf; +use thiserror::Error; + +pub fn read_data_root() -> Result, DataRootError> { + todo!() +} + +/// Represents an error when read or write data root fails. +#[derive(Debug, Error)] +pub enum DataRootError {}