1
0

feat: finish highlevel

This commit is contained in:
2026-05-08 14:08:51 +08:00
parent e325ba08f1
commit ec5c78e8ce

View File

@@ -51,6 +51,8 @@ pub enum ParseProgramError {
pub enum ProgramError { pub enum ProgramError {
#[error("{0}")] #[error("{0}")]
Lowlevel(#[from] lowlevel::Error), Lowlevel(#[from] lowlevel::Error),
#[error("given index is invalid")]
BadIndex,
} }
// endregion // endregion
@@ -236,8 +238,11 @@ pub struct Program {
icon: Option<Rc<ProgramIcon>>, icon: Option<Rc<ProgramIcon>>,
behavior: Option<Rc<ProgramBehavior>>, behavior: Option<Rc<ProgramBehavior>>,
#[allow(dead_code)]
strs: Vec<Rc<ProgramStr>>, strs: Vec<Rc<ProgramStr>>,
#[allow(dead_code)]
icons: Vec<Rc<ProgramIcon>>, icons: Vec<Rc<ProgramIcon>>,
#[allow(dead_code)]
behaviors: Vec<Rc<ProgramBehavior>>, behaviors: Vec<Rc<ProgramBehavior>>,
ext_keys: Vec<ProgramProgIdExtKey>, ext_keys: Vec<ProgramProgIdExtKey>,
@@ -463,8 +468,8 @@ impl Program {
// Create ProgId subkeys one by one // Create ProgId subkeys one by one
debug_println!("Adding ProgId subkey..."); debug_println!("Adding ProgId subkey...");
for program_progid_key in &mut self.ext_keys { for program_key in &mut self.ext_keys {
let progid_key = &mut program_progid_key.progid_key; let progid_key = &mut program_key.progid_key;
debug_println!( debug_println!(
"Adding ProgId \"{0}\" subkey...", "Adding ProgId \"{0}\" subkey...",
progid_key.inner().to_string() progid_key.inner().to_string()
@@ -473,14 +478,14 @@ impl Program {
// Create ProgId subkey // Create ProgId subkey
progid_key.ensure(scope)?; progid_key.ensure(scope)?;
// Write ProgId values // Write ProgId values
let name = Some(&program_progid_key.name.inner); let name = Some(&program_key.name.inner);
progid_key.set_default(scope, name)?; progid_key.set_default(scope, name)?;
progid_key.set_shell_verb(scope, &program_progid_key.behavior.inner)?; progid_key.set_shell_verb(scope, &program_key.behavior.inner)?;
progid_key.set_friendly_type_name(scope, name)?; progid_key.set_friendly_type_name(scope, name)?;
progid_key.set_default_icon(scope, Some(&program_progid_key.icon.inner))?; progid_key.set_default_icon(scope, Some(&program_key.icon.inner))?;
// Add this progid to file extension "open with" list. // Add this progid to file extension "open with" list.
let ext_key = &mut program_progid_key.ext_key; let ext_key = &mut program_key.ext_key;
ext_key.add_into_open_with_progids(scope, progid_key.inner())?; ext_key.add_into_open_with_progids(scope, progid_key.inner())?;
} }
@@ -505,8 +510,8 @@ impl Program {
// Delete ProgId subkeys one by one. // Delete ProgId subkeys one by one.
debug_println!("Adding ProgId subkey..."); debug_println!("Adding ProgId subkey...");
for program_progid_key in &mut self.ext_keys { for program_key in &mut self.ext_keys {
let progid_key = &mut program_progid_key.progid_key; let progid_key = &mut program_key.progid_key;
debug_println!( debug_println!(
"Deleting ProgId \"{0}\" subkey...", "Deleting ProgId \"{0}\" subkey...",
progid_key.inner().to_string() progid_key.inner().to_string()
@@ -518,7 +523,7 @@ impl Program {
// So we simply remove it from "open with" list. // So we simply remove it from "open with" list.
// Remove this ProgId from file extension "open with" list. // Remove this ProgId from file extension "open with" list.
let ext_key = &mut program_progid_key.ext_key; let ext_key = &mut program_key.ext_key;
ext_key.remove_from_open_with_progids(scope, progid_key.inner())?; ext_key.remove_from_open_with_progids(scope, progid_key.inner())?;
// Delete ProgId subkey // Delete ProgId subkey
@@ -551,8 +556,8 @@ impl Program {
// Check ProgId subkey. // Check ProgId subkey.
debug_println!("Checking ProgId subkey..."); debug_println!("Checking ProgId subkey...");
for program_progid_key in &self.ext_keys { for program_key in &self.ext_keys {
let progid_key = &program_progid_key.progid_key; let progid_key = &program_key.progid_key;
debug_println!( debug_println!(
"Checking ProgId \"{0}\" subkey...", "Checking ProgId \"{0}\" subkey...",
progid_key.inner().to_string() progid_key.inner().to_string()
@@ -567,16 +572,115 @@ impl Program {
Ok(true) Ok(true)
} }
pub fn link_ext(&self, scope: Scope, index: usize) -> Result<(), ProgramError> { pub fn link_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
todo!() match self.ext_keys.get_mut(index) {
Some(program_key) => {
let ext_key = &mut program_key.ext_key;
let progid_key = &program_key.progid_key;
// Before setting it, we must make sure this extension is existing
ext_key.ensure(scope)?;
ext_key.set_default(scope, Some(progid_key.inner()))?;
Ok(())
}
None => Err(ProgramError::BadIndex),
}
} }
pub fn unlink_ext(&self, scope: Scope, index: usize) -> Result<(), ProgramError> { pub fn unlink_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
todo!() match self.ext_keys.get_mut(index) {
Some(program_key) => {
let ext_key = &mut program_key.ext_key;
// Before setting it, we must make sure this extension is existing
ext_key.ensure(scope)?;
ext_key.set_default(scope, None)?;
Ok(())
}
None => Err(ProgramError::BadIndex),
}
} }
pub fn ext_status(&self, view: View, index: usize) -> Result<(), ProgramError> { pub fn ext_status(
todo!() &self,
view: View,
index: usize,
) -> Result<Option<ProgramExtStatus>, ProgramError> {
match self.ext_keys.get(index) {
Some(program_key) => {
let ext_key = &program_key.ext_key;
// If there is no such extension key, return None about this extension.
if !ext_key.is_exist(view)? {
return Ok(None);
}
// Let we fetch its associated default ProgId.
// If there is no such key, return None instead.
let progid = match ext_key.get_default(view)? {
Some(progid) => progid,
None => return Ok(None),
};
// Now we build ProgId key from gotten association
let progid_key = lowlevel::ProgIdKey::new(progid);
// If this associated ProgId key is not presented,
// we return None instead.
if !progid_key.is_exist(view)? {
return Ok(None);
}
// Now try fetch its diaplay name in modern way first.
// If there is no modern way, use legacy way instead.
// If there is still no display name, use ProgId self instead as display name.
let name = match progid_key.get_friendly_type_name(view)? {
Some(name) => name.extract()?,
None => match progid_key.get_default(view)? {
Some(name) => name.extract()?,
None => progid_key.inner().to_string(),
},
};
// Now try to fetch icon.
let icon = progid_key
.get_default_icon(view)?
.map(|ico| ico.extract(concept::IconSizeKind::Small))
.transpose()?;
// Okey, return it.
Ok(Some(ProgramExtStatus::new(name, icon)))
}
None => Err(ProgramError::BadIndex),
}
}
}
// endregion
// region: Program Exposed Structs
/// Exposed struct representing the default associated program of specific file extension.
///
/// The data including the diaplay name and icon.
pub struct ProgramExtStatus {
name: String,
icon: Option<concept::IconRc>,
}
impl ProgramExtStatus {
fn new(name: String, icon: Option<concept::IconRc>) -> Self {
Self { name, icon }
}
/// Get the display name of this program.
///
/// The program provided display name will be used firstly.
/// If this program has no display name, the stringified ProgId will be used instead.
pub fn get_name(&self) -> &str {
self.name.as_str()
}
/// Get the icon of this program.
///
/// Due to the icon is optional, if there is no icon, return None.
pub fn get_icon(&self) -> Option<&concept::IconRc> {
self.icon.as_ref()
} }
} }