feat(printers): types de papier et mode de couleur par defaut

Le tiroir de details expose desormais MediaType et ColorModel en plus de PageSize, cupsPrintQuality et Duplex, avec des libellets localises pour les valeurs usuelles (papier ordinaire, photo brillante/mate/satinee, couleur, niveaux de gris...). Persiste via lpadmin -o comme les autres options.
This commit is contained in:
Lionel DARNIS 2026-08-08 16:42:48 +02:00
parent 8d528f9e45
commit c2c7d9ccb1
4 changed files with 157 additions and 1 deletions

View file

@ -203,11 +203,16 @@ pub async fn remove_printer(name: &str) -> Result<(), String> {
/// Default job options supported by a queue, with their current values.
///
/// Values are taken from the queue's PPD view (`lpoptions -l`): `PageSize`,
/// `cupsPrintQuality` and `Duplex`, which `lpadmin -o` can persist.
/// `MediaType`, `ColorModel`, `cupsPrintQuality` and `Duplex`, which
/// `lpadmin -o` can persist.
#[derive(Clone, Debug, Default)]
pub struct PrinterOptions {
pub media: Vec<String>,
pub media_default: Option<String>,
pub media_types: Vec<String>,
pub media_type_default: Option<String>,
pub color_models: Vec<String>,
pub color_model_default: Option<String>,
pub qualities: Vec<String>,
pub quality_default: Option<String>,
pub sides: Vec<String>,
@ -237,6 +242,8 @@ pub async fn printer_options(name: &str) -> Result<PrinterOptions, String> {
let (list, default) = match key {
"PageSize" => (&mut options.media, &mut options.media_default),
"MediaType" => (&mut options.media_types, &mut options.media_type_default),
"ColorModel" => (&mut options.color_models, &mut options.color_model_default),
"cupsPrintQuality" => (&mut options.qualities, &mut options.quality_default),
"Duplex" => (&mut options.sides, &mut options.sides_default),
_ => continue,

View file

@ -129,6 +129,41 @@ fn quality_label(value: &str) -> String {
}
}
fn media_type_label(value: &str) -> String {
match value {
"Stationery" => fl!("printers-media-type-stationery"),
"Photographic" => fl!("printers-media-type-photographic"),
"PhotographicGlossy" => fl!("printers-media-type-photographic-glossy"),
"PhotographicMatte" => fl!("printers-media-type-photographic-matte"),
"PhotographicSatin" => fl!("printers-media-type-photographic-satin"),
"StationeryCoated" => fl!("printers-media-type-stationery-coated"),
"StationeryFine" => fl!("printers-media-type-stationery-fine"),
"StationeryInkjet" => fl!("printers-media-type-stationery-inkjet"),
"StationeryLetterhead" => fl!("printers-media-type-stationery-letterhead"),
"StationeryPreprint" => fl!("printers-media-type-stationery-preprint"),
"StationeryRecycled" => fl!("printers-media-type-stationery-recycled"),
"Envelope" => fl!("printers-media-type-envelope"),
"Transparency" => fl!("printers-media-type-transparency"),
"Labels" => fl!("printers-media-type-labels"),
"Cardstock" => fl!("printers-media-type-cardstock"),
_ => value.to_string(),
}
}
fn color_model_label(value: &str) -> String {
match value {
"RGB" => fl!("printers-color-rgb"),
"RGB16" => fl!("printers-color-rgb-16"),
"RGB24" => fl!("printers-color-rgb-24"),
"RGB48" => fl!("printers-color-rgb-48"),
"Gray" | "KGray" => fl!("printers-color-gray"),
"CMYK" => fl!("printers-color-cmyk"),
"CMY" => fl!("printers-color-cmy"),
"Black" => fl!("printers-color-black"),
_ => value.to_string(),
}
}
fn sides_label(value: &str) -> String {
match value {
"None" => fl!("printers-sides-one-sided"),
@ -551,6 +586,8 @@ impl Page {
if let Some((options_name, options)) = self.options.as_ref()
&& options_name == &printer.name
&& (!options.media.is_empty()
|| !options.media_types.is_empty()
|| !options.color_models.is_empty()
|| !options.qualities.is_empty()
|| !options.sides.is_empty())
{
@ -589,6 +626,68 @@ impl Page {
);
}
if !options.media_types.is_empty() {
let values = options.media_types.clone();
let selected = options
.media_type_default
.as_ref()
.and_then(|default| values.iter().position(|value| value == default));
let labels: Vec<String> = values.iter().map(|v| media_type_label(v)).collect();
let name = printer.name.clone();
list = list.add(
widget::settings::item::builder(fl!("printers-option-media-type")).control(
widget::dropdown::popup_dropdown(
labels,
selected,
move |index| Message::SetOption {
printer: name.clone(),
option: "MediaType".to_string(),
value: values.get(index).cloned().unwrap_or_default(),
},
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|action| {
crate::app::Message::PageMessage(
crate::pages::Message::Printers(action),
)
},
),
),
);
}
if !options.color_models.is_empty() {
let values = options.color_models.clone();
let selected = options
.color_model_default
.as_ref()
.and_then(|default| values.iter().position(|value| value == default));
let labels: Vec<String> = values.iter().map(|v| color_model_label(v)).collect();
let name = printer.name.clone();
list = list.add(
widget::settings::item::builder(fl!("printers-option-color")).control(
widget::dropdown::popup_dropdown(
labels,
selected,
move |index| Message::SetOption {
printer: name.clone(),
option: "ColorModel".to_string(),
value: values.get(index).cloned().unwrap_or_default(),
},
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|action| {
crate::app::Message::PageMessage(
crate::pages::Message::Printers(action),
)
},
),
),
);
}
if !options.qualities.is_empty() {
let values = options.qualities.clone();
let selected = options