You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.0 KiB
163 lines
5.0 KiB
use std::sync::Arc; |
|
|
|
use ashpd::{desktop::settings::Settings as SettingsProxy, zvariant}; |
|
use futures_util::StreamExt; |
|
use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*}; |
|
use tracing::error; |
|
|
|
use super::{ClockFormat, SystemSettings, SystemSettingsImpl}; |
|
use crate::{spawn, spawn_tokio}; |
|
|
|
const GNOME_DESKTOP_NAMESPACE: &str = "org.gnome.desktop.interface"; |
|
const CLOCK_FORMAT_KEY: &str = "clock-format"; |
|
|
|
mod imp { |
|
use super::*; |
|
|
|
#[derive(Debug, Default)] |
|
pub struct LinuxSystemSettings {} |
|
|
|
#[glib::object_subclass] |
|
impl ObjectSubclass for LinuxSystemSettings { |
|
const NAME: &'static str = "LinuxSystemSettings"; |
|
type Type = super::LinuxSystemSettings; |
|
type ParentType = SystemSettings; |
|
} |
|
|
|
impl ObjectImpl for LinuxSystemSettings { |
|
fn constructed(&self) { |
|
self.parent_constructed(); |
|
|
|
spawn!(clone!( |
|
#[weak(rename_to = imp)] |
|
self, |
|
async move { |
|
imp.init().await; |
|
} |
|
)); |
|
} |
|
} |
|
|
|
impl SystemSettingsImpl for LinuxSystemSettings {} |
|
|
|
impl LinuxSystemSettings { |
|
/// Initialize the system settings. |
|
async fn init(&self) { |
|
let obj = self.obj(); |
|
|
|
let proxy = match spawn_tokio!(async move { SettingsProxy::new().await }) |
|
.await |
|
.expect("task was not aborted") |
|
{ |
|
Ok(proxy) => proxy, |
|
Err(error) => { |
|
error!("Could not access settings portal: {error}"); |
|
return; |
|
} |
|
}; |
|
let proxy = Arc::new(proxy); |
|
|
|
let proxy_clone = proxy.clone(); |
|
match spawn_tokio!(async move { |
|
proxy_clone |
|
.read::<ClockFormat>(GNOME_DESKTOP_NAMESPACE, CLOCK_FORMAT_KEY) |
|
.await |
|
}) |
|
.await |
|
.expect("task was not aborted") |
|
{ |
|
Ok(clock_format) => obj |
|
.upcast_ref::<SystemSettings>() |
|
.set_clock_format(clock_format), |
|
Err(error) => { |
|
error!("Could not access clock format system setting: {error}"); |
|
return; |
|
} |
|
} |
|
|
|
let clock_format_changed_stream = match spawn_tokio!(async move { |
|
proxy |
|
.receive_setting_changed_with_args::<ClockFormat>( |
|
GNOME_DESKTOP_NAMESPACE, |
|
CLOCK_FORMAT_KEY, |
|
) |
|
.await |
|
}) |
|
.await |
|
.expect("task was not aborted") |
|
{ |
|
Ok(stream) => stream, |
|
Err(error) => { |
|
error!( |
|
"Could not listen to changes of the clock format system setting: {error}" |
|
); |
|
return; |
|
} |
|
}; |
|
|
|
let obj_weak = obj.downgrade(); |
|
clock_format_changed_stream.for_each(move |value| { |
|
let obj_weak = obj_weak.clone(); |
|
async move { |
|
let clock_format = match value { |
|
Ok(clock_format) => clock_format, |
|
Err(error) => { |
|
error!("Could not update clock format setting: {error}"); |
|
return; |
|
} |
|
}; |
|
|
|
if let Some(obj) = obj_weak.upgrade() { |
|
obj.upcast_ref::<SystemSettings>().set_clock_format(clock_format); |
|
} else { |
|
error!("Could not update clock format setting: could not upgrade weak reference"); |
|
} |
|
} |
|
}).await; |
|
} |
|
} |
|
} |
|
|
|
glib::wrapper! { |
|
/// API to access system settings on Linux. |
|
pub struct LinuxSystemSettings(ObjectSubclass<imp::LinuxSystemSettings>) |
|
@extends SystemSettings; |
|
} |
|
|
|
impl LinuxSystemSettings { |
|
pub fn new() -> Self { |
|
glib::Object::new() |
|
} |
|
} |
|
|
|
impl Default for LinuxSystemSettings { |
|
fn default() -> Self { |
|
Self::new() |
|
} |
|
} |
|
|
|
impl TryFrom<&zvariant::OwnedValue> for ClockFormat { |
|
type Error = zvariant::Error; |
|
|
|
fn try_from(value: &zvariant::OwnedValue) -> Result<Self, Self::Error> { |
|
let Ok(s) = <&str>::try_from(value) else { |
|
return Err(zvariant::Error::IncorrectType); |
|
}; |
|
|
|
match s { |
|
"12h" => Ok(Self::TwelveHours), |
|
"24h" => Ok(Self::TwentyFourHours), |
|
_ => Err(zvariant::Error::Message(format!( |
|
"Invalid string `{s}`, expected `12h` or `24h`" |
|
))), |
|
} |
|
} |
|
} |
|
|
|
impl TryFrom<zvariant::OwnedValue> for ClockFormat { |
|
type Error = zvariant::Error; |
|
|
|
fn try_from(value: zvariant::OwnedValue) -> Result<Self, Self::Error> { |
|
Self::try_from(&value) |
|
} |
|
}
|
|
|