use crate::{utils, Initializer, QtInstallation, QtTool};
use semver::Version;
use std::{
ffi::{OsStr, OsString},
path::{Path, PathBuf},
process::Command,
};
pub struct QtToolRcc {
executable: PathBuf,
qt_version: Version,
custom_args: Vec<OsString>,
}
impl QtToolRcc {
pub fn new(qt_installation: &dyn QtInstallation) -> Self {
let executable = qt_installation
.try_find_tool(QtTool::Rcc)
.expect("Could not find rcc");
utils::check_executable_help(&executable).unwrap();
let qt_version = qt_installation.version();
Self {
executable,
qt_version,
custom_args: Vec::new(),
}
}
pub fn custom_args(mut self, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> Self {
self.custom_args = args
.into_iter()
.map(|s| s.as_ref().to_os_string())
.collect();
self
}
pub fn compile(&self, input_file: impl AsRef<Path>) -> Initializer {
let input_path = input_file.as_ref();
let output_folder = QtTool::Rcc.writable_path();
std::fs::create_dir_all(&output_folder).expect("Could not create qrc dir");
let mut output_path = output_folder.join(input_path.file_name().unwrap());
output_path.set_extension("cpp");
let name = input_path
.file_name()
.unwrap()
.to_string_lossy()
.replace('.', "_");
let mut args = vec![
OsString::from(input_path),
OsString::from("-o"),
OsString::from(&output_path),
OsString::from("--name"),
OsString::from(&name),
];
args.extend(self.custom_args.iter().cloned());
let cmd = Command::new(&self.executable)
.env_clear()
.args(args)
.output()
.unwrap_or_else(|_| panic!("rcc failed for {}", input_path.display()));
if !cmd.status.success() {
panic!(
"rcc failed for {}:\n{}",
input_path.display(),
String::from_utf8_lossy(&cmd.stderr)
);
}
let qt_6_5 = Version::new(6, 5, 0);
let init_header = if self.qt_version >= qt_6_5 {
"QtCore/QtResource"
} else {
"QtCore/QDir"
};
Initializer {
file: Some(output_path),
init_call: Some(format!("Q_INIT_RESOURCE({name});")),
init_declaration: Some(format!("#include <{init_header}>")),
}
}
pub fn list(&self, input_file: impl AsRef<Path>) -> Vec<PathBuf> {
let input_path = input_file.as_ref();
let cmd_list = Command::new(&self.executable)
.args(["--list", input_path.to_str().unwrap()])
.env_clear()
.output()
.unwrap_or_else(|_| panic!("rcc --list failed for {}", input_path.display()));
if !cmd_list.status.success() {
panic!(
"rcc --list failed for {}:\n{}",
input_path.display(),
String::from_utf8_lossy(&cmd_list.stderr)
);
}
String::from_utf8_lossy(&cmd_list.stdout)
.split_terminator('\n')
.map(PathBuf::from)
.collect()
}
}