feat: partial implementation of wallpaper settings
Will take some time to refactor the rest
This commit is contained in:
parent
14a4a23bc9
commit
a4eee2186c
14 changed files with 375 additions and 80 deletions
|
|
@ -235,19 +235,16 @@ impl Application for SettingsApp {
|
|||
Message::None | Message::Search(_) => {}
|
||||
Message::PageMessage(message) => match message {
|
||||
crate::pages::Message::About(message) => {
|
||||
if let Some(page) = self.pages.page_mut::<system::about::Page>() {
|
||||
page.update(message);
|
||||
}
|
||||
page::update!(self.pages, message, system::about::Page);
|
||||
}
|
||||
crate::pages::Message::DateAndTime(message) => {
|
||||
if let Some(page) = self.pages.page_mut::<time::date::Page>() {
|
||||
page.update(message);
|
||||
}
|
||||
page::update!(self.pages, message, time::date::Page);
|
||||
}
|
||||
crate::pages::Message::Desktop(message) => {
|
||||
if let Some(page) = self.pages.page_mut::<desktop::Page>() {
|
||||
page.update(message);
|
||||
}
|
||||
page::update!(self.pages, message, desktop::Page);
|
||||
}
|
||||
crate::pages::Message::DesktopWallpaper(message) => {
|
||||
page::update!(self.pages, message, desktop::wallpaper::Page);
|
||||
}
|
||||
crate::pages::Message::External { .. } => {
|
||||
todo!("external plugins not supported yet");
|
||||
|
|
@ -457,7 +454,10 @@ impl SettingsApp {
|
|||
);
|
||||
}
|
||||
|
||||
settings::view_column(column_widgets).into()
|
||||
settings::view_column(column_widgets)
|
||||
.max_width(683)
|
||||
.padding(0)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn search_changed(&mut self, phrase: String) {
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ pub fn main() -> color_eyre::Result<()> {
|
|||
let localizer = crate::localize::localizer();
|
||||
let requested_languages = DesktopLanguageRequester::requested_languages();
|
||||
|
||||
if let Err(error) = localizer.select(&requested_languages) {
|
||||
eprintln!("error while loading fluent localizations: {error}");
|
||||
if let Err(why) = localizer.select(&requested_languages) {
|
||||
tracing::error!(%why, "error while loading fluent localizations");
|
||||
}
|
||||
|
||||
cosmic::settings::set_default_icon_theme("Pop");
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ pub struct Page {
|
|||
pub show_applications_button: bool,
|
||||
pub show_minimize_button: bool,
|
||||
pub show_maximize_button: bool,
|
||||
pub slideshow: bool,
|
||||
pub same_background: bool,
|
||||
}
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
|
|
@ -39,10 +37,8 @@ impl page::AutoBind<crate::pages::Message> for Page {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
Slideshow(bool),
|
||||
SameBackground(bool),
|
||||
ShowWorkspacesButton(bool),
|
||||
ShowApplicationsButton(bool),
|
||||
ShowMinimizeButton(bool),
|
||||
|
|
@ -53,12 +49,10 @@ pub enum Message {
|
|||
impl Page {
|
||||
pub fn update(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::SameBackground(value) => self.same_background = value,
|
||||
Message::ShowApplicationsButton(value) => self.show_applications_button = value,
|
||||
Message::ShowMaximizeButton(value) => self.show_maximize_button = value,
|
||||
Message::ShowMinimizeButton(value) => self.show_minimize_button = value,
|
||||
Message::ShowWorkspacesButton(value) => self.show_workspaces_button = value,
|
||||
Message::Slideshow(value) => self.slideshow = value,
|
||||
Message::TopLeftHotCorner(value) => self.top_left_hot_corner = value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,74 @@
|
|||
// Copyright 2023 System76 <info@system76.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::Message;
|
||||
use std::{path::PathBuf, time::Instant};
|
||||
|
||||
use apply::Apply;
|
||||
use cosmic::{
|
||||
iced::widget::{column, container, horizontal_space, image, row, svg, text},
|
||||
iced::alignment::Horizontal,
|
||||
iced::widget::{column, container, horizontal_space, row, text},
|
||||
iced::Length,
|
||||
iced_runtime::core::image::Handle as ImageHandle,
|
||||
theme,
|
||||
widget::{list_column, settings, toggler},
|
||||
Element,
|
||||
};
|
||||
use cosmic_settings_desktop::wallpaper::{self, Entry, Output};
|
||||
use cosmic_settings_page::Section;
|
||||
use cosmic_settings_page::{self as page, section};
|
||||
use slotmap::SlotMap;
|
||||
use slotmap::{DefaultKey, SecondaryMap, SlotMap};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Page;
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
SameBackground(bool),
|
||||
Select(DefaultKey),
|
||||
Slideshow(bool),
|
||||
Update((wallpaper::Config, Context)),
|
||||
}
|
||||
|
||||
pub struct Page {
|
||||
pub config: wallpaper::Config,
|
||||
pub selection: Context,
|
||||
pub same_background: bool,
|
||||
pub slideshow: bool,
|
||||
}
|
||||
|
||||
impl Default for Page {
|
||||
fn default() -> Self {
|
||||
Page {
|
||||
config: wallpaper::Config::default(),
|
||||
selection: Context::default(),
|
||||
same_background: true,
|
||||
slideshow: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Context {
|
||||
active: DefaultKey,
|
||||
handles: SlotMap<DefaultKey, ImageHandle>,
|
||||
paths: SecondaryMap<DefaultKey, PathBuf>,
|
||||
}
|
||||
|
||||
impl Page {
|
||||
pub fn update(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::SameBackground(value) => self.same_background = value,
|
||||
Message::Select(id) => {
|
||||
if let Some(path) = self.selection.paths.get(id) {
|
||||
wallpaper::set(&mut self.config, Entry::new(Output::All, path.to_owned()));
|
||||
self.selection.active = id;
|
||||
}
|
||||
}
|
||||
Message::Slideshow(value) => self.slideshow = value,
|
||||
Message::Update((config, selection)) => {
|
||||
self.config = config;
|
||||
self.selection = selection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl page::Page<crate::pages::Message> for Page {
|
||||
fn content(
|
||||
|
|
@ -30,6 +83,32 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
.title(fl!("wallpaper"))
|
||||
.description(fl!("wallpaper", "desc"))
|
||||
}
|
||||
|
||||
fn load(&self, _page: page::Entity) -> Option<page::Task<crate::pages::Message>> {
|
||||
Some(Box::pin(async move {
|
||||
let config = wallpaper::config();
|
||||
|
||||
let mut backgrounds = wallpaper::load_each_from_path("/usr/share/backgrounds".into());
|
||||
let mut update = Context::default();
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
while let Some((path, image)) = backgrounds.recv().await {
|
||||
let handle =
|
||||
ImageHandle::from_pixels(image.width(), image.height(), image.into_vec());
|
||||
|
||||
let id = update.handles.insert(handle);
|
||||
update.paths.insert(id, path);
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"loaded wallpapers in {:?}",
|
||||
Instant::now().duration_since(start)
|
||||
);
|
||||
|
||||
crate::pages::Message::DesktopWallpaper(Message::Update((config, update)))
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||
|
|
@ -42,57 +121,84 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
fl!("wallpaper", "slide"),
|
||||
fl!("wallpaper", "change"),
|
||||
])
|
||||
.view::<Page>(|binder, _page, section| {
|
||||
let desktop = binder
|
||||
.page::<super::Page>()
|
||||
.expect("desktop page not found");
|
||||
.view::<Page>(|_binder, page, section| {
|
||||
let descriptions = §ion.descriptions;
|
||||
let image_paths: Vec<std::path::PathBuf> = Vec::new();
|
||||
|
||||
let mut image_column = Vec::with_capacity(image_paths.len() / 4);
|
||||
for chunk in image_paths.chunks(4) {
|
||||
let mut image_row = Vec::with_capacity(chunk.len());
|
||||
for image_path in chunk.iter() {
|
||||
image_row.push(if image_path.ends_with(".svg") {
|
||||
svg(svg::Handle::from_path(image_path))
|
||||
.width(Length::Fixed(150.))
|
||||
.into()
|
||||
} else {
|
||||
image(image_path).width(Length::Fixed(150.)).into()
|
||||
});
|
||||
let mut image_column = Vec::with_capacity(page.selection.handles.len() / 4);
|
||||
let mut image_handles = page.selection.handles.iter();
|
||||
|
||||
while let Some((id, handle)) = image_handles.next() {
|
||||
let mut image_row = Vec::with_capacity(4);
|
||||
|
||||
image_row.push(wallpaper_button(handle, id));
|
||||
|
||||
for (id, handle) in image_handles.by_ref().take(3) {
|
||||
image_row.push(wallpaper_button(handle, id));
|
||||
}
|
||||
|
||||
image_column.push(row(image_row).spacing(16).into());
|
||||
}
|
||||
|
||||
let children = vec![
|
||||
row!(
|
||||
let mut children = Vec::with_capacity(3);
|
||||
|
||||
if let Some(image) = page.selection.handles.get(page.selection.active) {
|
||||
let display_preview = row!(
|
||||
horizontal_space(Length::Fill),
|
||||
container(
|
||||
image("/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png")
|
||||
.width(Length::Fixed(300.))
|
||||
cosmic::iced::widget::image(image.clone()).width(Length::Fixed(300.0))
|
||||
)
|
||||
.padding(4)
|
||||
.style(theme::Container::Background),
|
||||
horizontal_space(Length::Fill),
|
||||
)
|
||||
.into(),
|
||||
.padding([0, 0, 8, 0])
|
||||
.into();
|
||||
|
||||
children.push(display_preview);
|
||||
}
|
||||
|
||||
children.push(
|
||||
cosmic::widget::text("All Displays")
|
||||
.horizontal_alignment(Horizontal::Center)
|
||||
.width(Length::Fill)
|
||||
.apply(cosmic::iced::widget::container)
|
||||
.width(Length::Fill)
|
||||
.padding([0, 0, 16, 0])
|
||||
.into(),
|
||||
);
|
||||
|
||||
children.push(
|
||||
list_column()
|
||||
.add(settings::item(
|
||||
&descriptions[0],
|
||||
toggler(None, desktop.same_background, Message::SameBackground),
|
||||
toggler(None, page.same_background, Message::SameBackground),
|
||||
))
|
||||
.add(settings::item(&descriptions[1], text("TODO")))
|
||||
.add(settings::item(
|
||||
&descriptions[2],
|
||||
toggler(None, desktop.slideshow, Message::Slideshow),
|
||||
toggler(None, page.slideshow, Message::Slideshow),
|
||||
))
|
||||
.into(),
|
||||
column(image_column).spacing(16).into(),
|
||||
];
|
||||
);
|
||||
|
||||
settings::view_column(children)
|
||||
children.push(column(image_column).spacing(12).padding(0).into());
|
||||
|
||||
cosmic::iced::widget::column(children)
|
||||
.spacing(22)
|
||||
.padding(0)
|
||||
.max_width(683)
|
||||
.apply(Element::from)
|
||||
.map(crate::pages::Message::Desktop)
|
||||
.map(crate::pages::Message::DesktopWallpaper)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wallpaper_button(handle: &ImageHandle, id: DefaultKey) -> Element<Message> {
|
||||
let image = cosmic::iced::widget::image(handle.clone()).apply(cosmic::iced::Element::from);
|
||||
|
||||
cosmic::iced::widget::button(image)
|
||||
.width(Length::Fixed(158.0))
|
||||
.height(Length::Fixed(105.0))
|
||||
.style(cosmic::theme::Button::Transparent)
|
||||
.on_press(Message::Select(id))
|
||||
.into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ pub enum Message {
|
|||
DateAndTime(time::date::Message),
|
||||
Desktop(desktop::Message),
|
||||
Panel(desktop::panel::Message),
|
||||
DesktopWallpaper(desktop::wallpaper::Message),
|
||||
External { id: String, message: Vec<u8> },
|
||||
Page(Entity),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub fn search_header<Message>(
|
|||
|
||||
column_children.push(
|
||||
text(parent_meta.title.as_str())
|
||||
.size(16)
|
||||
.size(14)
|
||||
.apply(container)
|
||||
.padding([0, 0, 0, 6])
|
||||
.into(),
|
||||
|
|
@ -47,7 +47,7 @@ pub fn search_header<Message>(
|
|||
#[must_use]
|
||||
pub fn search_page_link<Message: 'static>(title: &str) -> Button<Message, cosmic::Renderer> {
|
||||
text(title)
|
||||
.size(32)
|
||||
.size(24)
|
||||
.horizontal_alignment(iced::alignment::Horizontal::Left)
|
||||
.apply(button)
|
||||
.style(cosmic::theme::Button::Link)
|
||||
|
|
@ -56,7 +56,7 @@ pub fn search_page_link<Message: 'static>(title: &str) -> Button<Message, cosmic
|
|||
#[must_use]
|
||||
pub fn page_title<Message: 'static>(page: &page::Info) -> Element<Message> {
|
||||
row!(
|
||||
text(page.title.as_str()).size(32),
|
||||
text(page.title.as_str()).size(24),
|
||||
horizontal_space(Length::Fill)
|
||||
)
|
||||
.into()
|
||||
|
|
@ -71,13 +71,13 @@ pub fn parent_page_button<'a, Message: Clone + 'static>(
|
|||
column!(
|
||||
button(row!(
|
||||
icon("go-previous-symbolic", 20).style(theme::Svg::SymbolicLink),
|
||||
text(parent.title.as_str()).size(20),
|
||||
text(parent.title.as_str()).size(14),
|
||||
))
|
||||
.padding(0)
|
||||
.style(theme::Button::Link)
|
||||
.on_press(on_press),
|
||||
row!(
|
||||
text(sub_page.title.as_str()).size(32),
|
||||
text(sub_page.title.as_str()).size(24),
|
||||
horizontal_space(Length::Fill),
|
||||
)
|
||||
.align_items(iced::alignment::Alignment::Center),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue