fix(wallpaper): improvements and fixes
This commit is contained in:
parent
39eccde230
commit
bf70b14cda
12 changed files with 261 additions and 168 deletions
|
|
@ -34,20 +34,51 @@ impl Config {
|
|||
}
|
||||
};
|
||||
|
||||
// Get the active background folder from cosmic-config.
|
||||
if let Ok(path) = context.get::<Option<PathBuf>>(CURRENT_FOLDER) {
|
||||
config.current_folder = path;
|
||||
// Set current folder if it exists.
|
||||
config.current_folder = path.filter(|path| path.exists());
|
||||
}
|
||||
|
||||
// Get custom colors stored in cosmic-config.
|
||||
if let Ok(colors) = context.get::<Vec<wallpaper::Color>>(CUSTOM_COLORS) {
|
||||
config.custom_colors = colors;
|
||||
}
|
||||
|
||||
// Get custom background images stored in cosmic-config.
|
||||
if let Ok(images) = context.get::<Vec<PathBuf>>(CUSTOM_IMAGES) {
|
||||
config.custom_images = images;
|
||||
// Update config if images are missing.
|
||||
let mut update_config = false;
|
||||
|
||||
for image in images {
|
||||
if image.exists() {
|
||||
config.custom_images.push(image);
|
||||
} else {
|
||||
update_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
if update_config {
|
||||
let _res = config.update_custom_images();
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(folders) = dbg!(context.get::<VecDeque<PathBuf>>(RECENT_FOLDERS)) {
|
||||
config.recent_folders = folders;
|
||||
// Get recently-added background folders from cosmic-config.
|
||||
if let Ok(folders) = context.get::<VecDeque<PathBuf>>(RECENT_FOLDERS) {
|
||||
// Update config if folders are missing
|
||||
let mut update_config = false;
|
||||
|
||||
for folder in folders {
|
||||
if folder.exists() {
|
||||
config.recent_folders.push_back(folder);
|
||||
} else {
|
||||
update_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
if update_config {
|
||||
let _res = config.update_recent_folders();
|
||||
}
|
||||
}
|
||||
|
||||
config.context = Some(context);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,15 @@ use std::{
|
|||
};
|
||||
|
||||
use apply::Apply;
|
||||
use cosmic::iced::{wayland::actions::window::SctkWindowSettings, window, Color, Length};
|
||||
use cosmic::iced_sctk::commands::window::{close_window, get_window};
|
||||
use cosmic::{
|
||||
iced::{wayland::actions::window::SctkWindowSettings, window, Color, Length},
|
||||
prelude::CollectionWidget,
|
||||
};
|
||||
use cosmic::{
|
||||
iced_core::Alignment,
|
||||
iced_sctk::commands::window::{close_window, get_window},
|
||||
widget::icon,
|
||||
};
|
||||
use cosmic::{
|
||||
iced_core::{alignment, layout},
|
||||
iced_runtime::core::image::Handle as ImageHandle,
|
||||
|
|
@ -57,35 +64,44 @@ pub type Image = ImageBuffer<Rgba<u8>, Vec<u8>>;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
ChangeCategory(Category),
|
||||
ChangeFolder(Context),
|
||||
ColorAddDialog,
|
||||
ColorDialogUpdate(ColorPickerUpdate),
|
||||
ColorRemove(wallpaper::Color),
|
||||
ChangeCategory(Category),
|
||||
ColorSelect(wallpaper::Color),
|
||||
DragColorDialog,
|
||||
Fit(usize),
|
||||
ImageAdd(Option<Arc<(PathBuf, Image, Image)>>),
|
||||
ImageAddDialog,
|
||||
ImageRemove(DefaultKey),
|
||||
Init(Box<(wallpaper::Config, HashMap<String, String>, Context)>),
|
||||
Output(segmented_button::Entity),
|
||||
RotationFrequency(usize),
|
||||
SameBackground(bool),
|
||||
SameWallpaper(bool),
|
||||
Select(DefaultKey),
|
||||
Slideshow(bool),
|
||||
Init(Box<(wallpaper::Config, HashMap<String, String>, Context)>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Category {
|
||||
Backgrounds,
|
||||
AddFolder,
|
||||
Colors,
|
||||
RecentFolder(usize),
|
||||
Wallpapers,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum ActiveDialog {
|
||||
AddFolder,
|
||||
AddImage,
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct Page {
|
||||
pub active_output: Option<String>,
|
||||
pub background_service_config: wallpaper::Config,
|
||||
active_dialog: ActiveDialog,
|
||||
pub wallpaper_service_config: wallpaper::Config,
|
||||
pub cached_display_handle: Option<ImageHandle>,
|
||||
pub categories: dropdown::multi::Model<String, Category>,
|
||||
pub color_dialog: window::Id,
|
||||
|
|
@ -116,21 +132,41 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
}
|
||||
|
||||
fn file_chooser(&mut self, selections: Vec<url::Url>) -> Command<crate::pages::Message> {
|
||||
let active_dialog = self.active_dialog;
|
||||
self.active_dialog = ActiveDialog::None;
|
||||
|
||||
if let Some(selection) = selections.first() {
|
||||
let path = PathBuf::from(selection.path());
|
||||
|
||||
if path.is_dir() {
|
||||
self.add_recent_folder(path);
|
||||
} else {
|
||||
if let Some(parent) = path.parent() {
|
||||
self.add_recent_folder(parent.to_owned());
|
||||
match active_dialog {
|
||||
ActiveDialog::AddFolder => {
|
||||
if path.is_dir() {
|
||||
self.add_recent_folder(path.clone());
|
||||
|
||||
let _res = self.config.set_current_folder(Some(path.clone()));
|
||||
|
||||
return cosmic::command::future(async move {
|
||||
crate::pages::Message::DesktopWallpaper(Message::ChangeFolder(
|
||||
change_folder(path).await,
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return cosmic::command::future(async move {
|
||||
let result = wallpaper::load_image_with_thumbnail(&mut Vec::new(), path).await;
|
||||
ActiveDialog::AddImage => {
|
||||
if path.is_file() {
|
||||
return cosmic::command::future(async move {
|
||||
let result =
|
||||
wallpaper::load_image_with_thumbnail(&mut Vec::new(), path).await;
|
||||
|
||||
crate::pages::Message::DesktopWallpaper(Message::ImageAdd(result.map(Arc::new)))
|
||||
});
|
||||
crate::pages::Message::DesktopWallpaper(Message::ImageAdd(
|
||||
result.map(Arc::new),
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ActiveDialog::None => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,12 +177,12 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
let current_folder = self.config.current_folder().to_owned();
|
||||
|
||||
Some(Box::pin(async move {
|
||||
let (background_service_config, outputs) = wallpaper::config();
|
||||
let (wallpaper_service_config, outputs) = wallpaper::config();
|
||||
|
||||
let update = change_folder(current_folder).await;
|
||||
|
||||
crate::pages::Message::DesktopWallpaper(Message::Init(Box::new((
|
||||
background_service_config,
|
||||
wallpaper_service_config,
|
||||
outputs,
|
||||
update,
|
||||
))))
|
||||
|
|
@ -159,6 +195,7 @@ impl page::AutoBind<crate::pages::Message> for Page {}
|
|||
impl Default for Page {
|
||||
fn default() -> Self {
|
||||
let mut page = Page {
|
||||
active_dialog: ActiveDialog::None,
|
||||
active_output: None,
|
||||
cached_display_handle: None,
|
||||
categories: {
|
||||
|
|
@ -166,7 +203,7 @@ impl Default for Page {
|
|||
|
||||
categories.insert(dropdown::multi::list(
|
||||
None,
|
||||
vec![(fl!("system-backgrounds"), Category::Backgrounds)],
|
||||
vec![(fl!("wallpaper", "plural"), Category::Wallpapers)],
|
||||
));
|
||||
|
||||
categories.insert(dropdown::multi::list(
|
||||
|
|
@ -174,16 +211,21 @@ impl Default for Page {
|
|||
vec![(fl!("colors"), Category::Colors)],
|
||||
));
|
||||
|
||||
categories.insert(dropdown::multi::list(
|
||||
None,
|
||||
vec![(fl!("open-new-folder"), Category::AddFolder)],
|
||||
));
|
||||
|
||||
categories.insert(dropdown::multi::list(
|
||||
Some(fl!("recent-folders")),
|
||||
Vec::with_capacity(5),
|
||||
));
|
||||
|
||||
categories.selected = Some(Category::Backgrounds);
|
||||
categories.selected = Some(Category::Wallpapers);
|
||||
|
||||
categories
|
||||
},
|
||||
background_service_config: wallpaper::Config::default(),
|
||||
wallpaper_service_config: wallpaper::Config::default(),
|
||||
color_dialog: window::Id::unique(),
|
||||
color_model: ColorPickerModel::new(fl!("hex"), fl!("rgb"), None, Some(Color::WHITE)),
|
||||
config: Config::new(),
|
||||
|
|
@ -233,7 +275,7 @@ impl Page {
|
|||
}
|
||||
|
||||
fn assign_recent_folders(&mut self) {
|
||||
let recent_list = &mut self.categories.lists[2];
|
||||
let recent_list = &mut self.categories.lists[3];
|
||||
recent_list.options.clear();
|
||||
|
||||
for (id, folder) in self.config.recent_folders().iter().enumerate() {
|
||||
|
|
@ -248,7 +290,7 @@ impl Page {
|
|||
|
||||
fn cache_display_image(&mut self) {
|
||||
let choice = match self.selection.active {
|
||||
Choice::Background(id) => self.selection.display_images.get(id),
|
||||
Choice::Wallpaper(id) => self.selection.display_images.get(id),
|
||||
|
||||
Choice::Slideshow => self.selection.display_images.values().next(),
|
||||
|
||||
|
|
@ -312,7 +354,7 @@ impl Page {
|
|||
}
|
||||
|
||||
fn config_output(&self) -> Option<String> {
|
||||
if self.background_service_config.same_on_all {
|
||||
if self.wallpaper_service_config.same_on_all {
|
||||
Some(String::from("all"))
|
||||
} else {
|
||||
self.outputs.active_data::<String>().cloned()
|
||||
|
|
@ -325,13 +367,13 @@ impl Page {
|
|||
return;
|
||||
};
|
||||
|
||||
if self.background_service_config.same_on_all {
|
||||
self.background_service_config.outputs.clear();
|
||||
if self.wallpaper_service_config.same_on_all {
|
||||
self.wallpaper_service_config.outputs.clear();
|
||||
}
|
||||
|
||||
let entry = match self.selection.active {
|
||||
Choice::Slideshow => {
|
||||
match self.config_background_entry(
|
||||
match self.config_wallpaper_entry(
|
||||
output.clone(),
|
||||
self.config.current_folder().to_path_buf(),
|
||||
) {
|
||||
|
|
@ -339,9 +381,10 @@ impl Page {
|
|||
None => return,
|
||||
}
|
||||
}
|
||||
Choice::Background(key) => {
|
||||
|
||||
Choice::Wallpaper(key) => {
|
||||
if let Some(path) = self.selection.paths.get(key) {
|
||||
match self.config_background_entry(output.clone(), path.clone()) {
|
||||
match self.config_wallpaper_entry(output.clone(), path.clone()) {
|
||||
Some(entry) => entry,
|
||||
None => return,
|
||||
}
|
||||
|
|
@ -356,30 +399,30 @@ impl Page {
|
|||
};
|
||||
|
||||
if output != "all" {
|
||||
self.background_service_config.backgrounds.clear();
|
||||
self.background_service_config.outputs.clear();
|
||||
self.wallpaper_service_config.backgrounds.clear();
|
||||
self.wallpaper_service_config.outputs.clear();
|
||||
}
|
||||
|
||||
wallpaper::set(&mut self.background_service_config, entry);
|
||||
wallpaper::set(&mut self.wallpaper_service_config, entry);
|
||||
}
|
||||
|
||||
/// Locate the ID of a background that's already stored in memory
|
||||
fn background_id_from_path(&self, path: &Path) -> Option<DefaultKey> {
|
||||
/// Locate the ID of a wallpaper that's already stored in memory
|
||||
fn wallpaper_id_from_path(&self, path: &Path) -> Option<DefaultKey> {
|
||||
self.selection
|
||||
.paths
|
||||
.iter()
|
||||
.find(|(_id, background)| *background == path)
|
||||
.find(|(_id, wallpaper)| *wallpaper == path)
|
||||
.map(|(id, _)| id)
|
||||
}
|
||||
|
||||
/// Updates configuration from the background service.
|
||||
fn background_service_config_update(
|
||||
/// Updates configuration from the wallpaper service.
|
||||
fn wallpaper_service_config_update(
|
||||
&mut self,
|
||||
background_service_config: wallpaper::Config,
|
||||
wallpaper_service_config: wallpaper::Config,
|
||||
displays: HashMap<String, String>,
|
||||
selection: Context,
|
||||
) {
|
||||
self.background_service_config = background_service_config;
|
||||
self.wallpaper_service_config = wallpaper_service_config;
|
||||
self.selection = selection;
|
||||
self.outputs.clear();
|
||||
|
||||
|
|
@ -400,43 +443,30 @@ impl Page {
|
|||
self.outputs.activate(id);
|
||||
}
|
||||
|
||||
if self.background_service_config.same_on_all
|
||||
|| self.background_service_config.backgrounds.is_empty()
|
||||
if self.wallpaper_service_config.same_on_all
|
||||
|| self.wallpaper_service_config.backgrounds.is_empty()
|
||||
{
|
||||
let entry = self.background_service_config.default_background.clone();
|
||||
self.select_background_entry(&entry);
|
||||
|
||||
if let Some(current) = entry_directory(self.config.current_folder(), &entry) {
|
||||
if let Err(why) = self.config.set_current_folder(Some(current)) {
|
||||
tracing::error!(?why, "cannot set current folder");
|
||||
}
|
||||
}
|
||||
let entry = self.wallpaper_service_config.default_background.clone();
|
||||
self.select_wallpaper_entry(&entry);
|
||||
} else if let Some(data) = self.outputs.active_data::<String>() {
|
||||
let mut backgrounds = Vec::new();
|
||||
let mut wallpapers = Vec::new();
|
||||
std::mem::swap(
|
||||
&mut self.background_service_config.backgrounds,
|
||||
&mut backgrounds,
|
||||
&mut self.wallpaper_service_config.backgrounds,
|
||||
&mut wallpapers,
|
||||
);
|
||||
|
||||
for background in &backgrounds {
|
||||
if &background.output == data {
|
||||
for wallpaper in &wallpapers {
|
||||
if &wallpaper.output == data {
|
||||
self.active_output = Some(data.clone());
|
||||
self.select_background_entry(background);
|
||||
|
||||
if let Some(current) = entry_directory(self.config.current_folder(), background)
|
||||
{
|
||||
if let Err(why) = self.config.set_current_folder(Some(current)) {
|
||||
tracing::error!(?why, "cannot set current folder");
|
||||
}
|
||||
}
|
||||
self.select_wallpaper_entry(wallpaper);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::swap(
|
||||
&mut self.background_service_config.backgrounds,
|
||||
&mut backgrounds,
|
||||
&mut self.wallpaper_service_config.backgrounds,
|
||||
&mut wallpapers,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -446,7 +476,7 @@ impl Page {
|
|||
let mut command = Command::none();
|
||||
|
||||
match category {
|
||||
Category::Backgrounds => {
|
||||
Category::Wallpapers => {
|
||||
if self.config.current_folder.is_some() {
|
||||
let _ = self.config.set_current_folder(None);
|
||||
command = cosmic::command::future(async move {
|
||||
|
|
@ -457,7 +487,7 @@ impl Page {
|
|||
))
|
||||
});
|
||||
} else {
|
||||
self.select_first_background();
|
||||
self.select_first_wallpaper();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -479,6 +509,19 @@ impl Page {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
Category::AddFolder => {
|
||||
self.active_dialog = ActiveDialog::AddFolder;
|
||||
return cosmic::command::message(crate::Message::FileChooser(
|
||||
crate::app::FileChooser::Open {
|
||||
title: fl!("wallpaper", "folder-dialog"),
|
||||
accept_label: fl!("dialog-add"),
|
||||
include_directories: true,
|
||||
modal: false,
|
||||
multiple_files: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
self.categories.selected = Some(category);
|
||||
|
|
@ -493,7 +536,7 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// Changes the slideshow background rotation frequency
|
||||
/// Changes the slideshow wallpaper rotation frequency
|
||||
pub fn change_rotation_frequency(&mut self, option: usize) {
|
||||
self.selected_rotation = option;
|
||||
|
||||
|
|
@ -508,8 +551,8 @@ impl Page {
|
|||
};
|
||||
}
|
||||
|
||||
/// Updates configuration for background image.
|
||||
fn config_background_entry(&self, output: String, path: PathBuf) -> Option<Entry> {
|
||||
/// Updates configuration for wallpaper image.
|
||||
fn config_wallpaper_entry(&self, output: String, path: PathBuf) -> Option<Entry> {
|
||||
let scaling_mode = match self.selected_fit {
|
||||
FIT => ScalingMode::Fit([0.0, 0.0, 0.0]),
|
||||
STRETCH => ScalingMode::Stretch,
|
||||
|
|
@ -589,13 +632,11 @@ impl Page {
|
|||
let selection = context.selection_handles.remove(image);
|
||||
|
||||
if let Some(((display, selection), path)) = display.zip(selection).zip(path) {
|
||||
let key = self.selection.paths.insert(path);
|
||||
self.selection.display_images.insert(key, display);
|
||||
self.selection.selection_handles.insert(key, selection);
|
||||
self.selection.add_custom_image(path, display, selection);
|
||||
}
|
||||
}
|
||||
|
||||
self.select_first_background();
|
||||
self.select_first_wallpaper();
|
||||
}
|
||||
|
||||
Message::ColorAddDialog => {
|
||||
|
|
@ -622,14 +663,23 @@ impl Page {
|
|||
tracing::error!(?path, ?why, "could add custom image to config");
|
||||
}
|
||||
|
||||
self.selection.add_custom_image(path, display, selection);
|
||||
self.selection.add_custom_image(
|
||||
path,
|
||||
display,
|
||||
ImageHandle::from_pixels(
|
||||
selection.width(),
|
||||
selection.height(),
|
||||
selection.into_vec(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Message::ImageAddDialog => {
|
||||
self.active_dialog = ActiveDialog::AddImage;
|
||||
return cosmic::command::message(crate::Message::FileChooser(
|
||||
crate::app::FileChooser::Open {
|
||||
title: fl!("wallpaper-dialog-image"),
|
||||
accept_label: fl!("wallpaper-dialog-image", "accept"),
|
||||
title: fl!("wallpaper", "image-dialog"),
|
||||
accept_label: fl!("dialog-add"),
|
||||
include_directories: false,
|
||||
modal: false,
|
||||
multiple_files: false,
|
||||
|
|
@ -663,13 +713,13 @@ impl Page {
|
|||
|
||||
Message::RotationFrequency(pos) => self.change_rotation_frequency(pos),
|
||||
|
||||
Message::SameBackground(value) => {
|
||||
self.background_service_config.same_on_all = value;
|
||||
self.background_service_config.backgrounds.clear();
|
||||
Message::SameWallpaper(value) => {
|
||||
self.wallpaper_service_config.same_on_all = value;
|
||||
self.wallpaper_service_config.backgrounds.clear();
|
||||
}
|
||||
|
||||
Message::Select(id) => {
|
||||
self.selection.active = Choice::Background(id);
|
||||
self.selection.active = Choice::Wallpaper(id);
|
||||
self.cache_display_image();
|
||||
}
|
||||
|
||||
|
|
@ -678,12 +728,12 @@ impl Page {
|
|||
self.selection.active = Choice::Slideshow;
|
||||
self.cache_display_image();
|
||||
} else {
|
||||
self.select_first_background();
|
||||
self.select_first_wallpaper();
|
||||
}
|
||||
}
|
||||
|
||||
Message::Init(update) => {
|
||||
self.background_service_config_update(update.0, update.1, update.2);
|
||||
self.wallpaper_service_config_update(update.0, update.1, update.2);
|
||||
self.config_apply();
|
||||
|
||||
// Sync custom colors from config.
|
||||
|
|
@ -692,7 +742,7 @@ impl Page {
|
|||
}
|
||||
|
||||
// Set the default selection if an image was selected.
|
||||
if let Choice::Background(_) | Choice::Slideshow = self.selection.active {
|
||||
if let Choice::Wallpaper(_) | Choice::Slideshow = self.selection.active {
|
||||
let folder = self.config.current_folder();
|
||||
for (id, recent) in self.config.recent_folders().iter().enumerate() {
|
||||
if recent == folder {
|
||||
|
|
@ -723,15 +773,15 @@ impl Page {
|
|||
Command::none()
|
||||
}
|
||||
|
||||
/// Selects the given background entry.
|
||||
fn select_background_entry(&mut self, entry: &wallpaper::Entry) {
|
||||
/// Selects the given wallpaper entry.
|
||||
fn select_wallpaper_entry(&mut self, entry: &wallpaper::Entry) {
|
||||
match entry.source {
|
||||
wallpaper::Source::Path(ref path) => {
|
||||
if path.is_dir() {
|
||||
self.selection.active = Choice::Slideshow;
|
||||
self.cache_display_image();
|
||||
} else if let Some(entity) = self.background_id_from_path(path) {
|
||||
self.select_background(entry, entity, path.is_dir());
|
||||
} else if let Some(entity) = self.wallpaper_id_from_path(path) {
|
||||
self.select_wallpaper(entry, entity, path.is_dir());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -743,25 +793,32 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// Selects the first background from the wallpaper select options.
|
||||
fn select_first_background(&mut self) {
|
||||
let (entity, path) = match self.selection.custom_images.last() {
|
||||
Some(entity) => (*entity, &self.selection.paths[*entity]),
|
||||
None => match self.selection.paths.iter().next() {
|
||||
/// Selects the first wallpaper from the wallpaper select options.
|
||||
fn select_first_wallpaper(&mut self) {
|
||||
let (entity, path) = if let Some(Category::Wallpapers) = self.categories.selected {
|
||||
match self.selection.custom_images.last() {
|
||||
Some(entity) => (*entity, &self.selection.paths[*entity]),
|
||||
None => match self.selection.paths.iter().next() {
|
||||
Some(value) => value,
|
||||
None => return,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match self.selection.paths.iter().next() {
|
||||
Some(value) => value,
|
||||
None => return,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(output) = self.config_output() {
|
||||
if let Some(entry) = self.config_background_entry(output, path.clone()) {
|
||||
self.select_background(&entry, entity, path.is_dir());
|
||||
if let Some(entry) = self.config_wallpaper_entry(output, path.clone()) {
|
||||
self.select_wallpaper(&entry, entity, path.is_dir());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Selects the given background
|
||||
fn select_background(
|
||||
/// Selects the given wallpaper
|
||||
fn select_wallpaper(
|
||||
&mut self,
|
||||
entry: &wallpaper::Entry,
|
||||
entity: DefaultKey,
|
||||
|
|
@ -770,7 +827,7 @@ impl Page {
|
|||
self.selection.active = if is_slideshow {
|
||||
Choice::Slideshow
|
||||
} else {
|
||||
Choice::Background(entity)
|
||||
Choice::Wallpaper(entity)
|
||||
};
|
||||
|
||||
match entry.scaling_mode {
|
||||
|
|
@ -805,14 +862,14 @@ impl Page {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum Choice {
|
||||
Background(DefaultKey),
|
||||
Wallpaper(DefaultKey),
|
||||
Color(wallpaper::Color),
|
||||
Slideshow,
|
||||
}
|
||||
|
||||
impl Default for Choice {
|
||||
fn default() -> Self {
|
||||
Self::Background(DefaultKey::default())
|
||||
Self::Wallpaper(DefaultKey::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -822,7 +879,7 @@ pub struct Context {
|
|||
custom_images: Vec<DefaultKey>,
|
||||
custom_colors: Vec<wallpaper::Color>,
|
||||
paths: SlotMap<DefaultKey, PathBuf>,
|
||||
is_custom: SecondaryMap<DefaultKey, bool>,
|
||||
is_custom: SecondaryMap<DefaultKey, ()>,
|
||||
display_images: SecondaryMap<DefaultKey, image::RgbaImage>,
|
||||
selection_handles: SecondaryMap<DefaultKey, ImageHandle>,
|
||||
}
|
||||
|
|
@ -834,15 +891,12 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_custom_image(&mut self, path: PathBuf, display: Image, selection: Image) {
|
||||
fn add_custom_image(&mut self, path: PathBuf, display: Image, selection: ImageHandle) {
|
||||
let key = self.paths.insert(path);
|
||||
self.is_custom.insert(key, true);
|
||||
self.is_custom.insert(key, ());
|
||||
self.display_images.insert(key, display);
|
||||
self.custom_images.push(key);
|
||||
self.selection_handles.insert(
|
||||
key,
|
||||
ImageHandle::from_pixels(selection.width(), selection.height(), selection.into_vec()),
|
||||
);
|
||||
self.selection_handles.insert(key, selection);
|
||||
}
|
||||
|
||||
fn remove_custom_color(&mut self, color: &wallpaper::Color) {
|
||||
|
|
@ -852,13 +906,14 @@ impl Context {
|
|||
}
|
||||
|
||||
fn remove_custom_image(&mut self, image: DefaultKey) -> Option<PathBuf> {
|
||||
if let Some(true) = self.is_custom.remove(image) {
|
||||
if self.is_custom.contains_key(image) {
|
||||
if let Some(id) = self.custom_images.iter().position(|i| i == &image) {
|
||||
self.custom_images.remove(id);
|
||||
}
|
||||
|
||||
self.display_images.remove(image);
|
||||
self.selection_handles.remove(image);
|
||||
self.is_custom.remove(image);
|
||||
return self.paths.remove(image);
|
||||
}
|
||||
|
||||
|
|
@ -868,9 +923,9 @@ impl Context {
|
|||
|
||||
pub async fn change_folder(current_folder: PathBuf) -> Context {
|
||||
let mut update = Context::default();
|
||||
let mut backgrounds = wallpaper::load_each_from_path(current_folder);
|
||||
let mut wallpapers = wallpaper::load_each_from_path(current_folder);
|
||||
|
||||
while let Some((path, display_image, selection_image)) = backgrounds.recv().await {
|
||||
while let Some((path, display_image, selection_image)) = wallpapers.recv().await {
|
||||
let id = update.paths.insert(path);
|
||||
|
||||
update.display_images.insert(id, display_image);
|
||||
|
|
@ -916,14 +971,14 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
|
||||
children.push(crate::widget::display_container(
|
||||
match page.selection.active {
|
||||
// Shows background options, with the slideshow toggle enabled
|
||||
// Shows wallpaper options, with the slideshow toggle enabled
|
||||
Choice::Slideshow => {
|
||||
slideshow_enabled = true;
|
||||
page.display_image_view()
|
||||
}
|
||||
|
||||
// Shows background options, with the slideshow toggle visible
|
||||
Choice::Background(_) => page.display_image_view(),
|
||||
// Shows wallpaper options, with the slideshow toggle visible
|
||||
Choice::Wallpaper(_) => page.display_image_view(),
|
||||
|
||||
// Displays color options, and hides the slideshow toggle
|
||||
Choice::Color(ref color) => {
|
||||
|
|
@ -938,7 +993,7 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
},
|
||||
));
|
||||
|
||||
children.push(if page.background_service_config.same_on_all {
|
||||
children.push(if page.wallpaper_service_config.same_on_all {
|
||||
text(fl!("all-displays"))
|
||||
.font(cosmic::font::FONT_SEMIBOLD)
|
||||
.horizontal_alignment(alignment::Horizontal::Center)
|
||||
|
|
@ -955,7 +1010,7 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
.into()
|
||||
});
|
||||
|
||||
let background_fit =
|
||||
let wallpaper_fit =
|
||||
cosmic::widget::dropdown(&page.fit_options, Some(page.selected_fit), Message::Fit);
|
||||
|
||||
children.push({
|
||||
|
|
@ -964,11 +1019,11 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
&*WALLPAPER_SAME,
|
||||
toggler(
|
||||
None,
|
||||
page.background_service_config.same_on_all,
|
||||
Message::SameBackground,
|
||||
page.wallpaper_service_config.same_on_all,
|
||||
Message::SameWallpaper,
|
||||
),
|
||||
))
|
||||
.add(settings::item(&*WALLPAPER_FIT, background_fit));
|
||||
.add(settings::item(&*WALLPAPER_FIT, wallpaper_fit));
|
||||
|
||||
if show_slideshow_toggle {
|
||||
column = column.add(settings::item(
|
||||
|
|
@ -997,38 +1052,50 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
let category_selection =
|
||||
dropdown::multi::dropdown(&page.categories, Message::ChangeCategory);
|
||||
|
||||
let add_button = {
|
||||
let (text, message) = if Some(Category::Colors) == page.categories.selected {
|
||||
(fl!("add-color"), Message::ColorAddDialog)
|
||||
} else {
|
||||
(fl!("add-image"), Message::ImageAddDialog)
|
||||
};
|
||||
// Show the add button only on the Colors and Wallpapers pages
|
||||
let add_button =
|
||||
if let Some(Category::Colors | Category::Wallpapers) = page.categories.selected {
|
||||
let (text, message) = if Some(Category::Colors) == page.categories.selected {
|
||||
(fl!("add-color"), Message::ColorAddDialog)
|
||||
} else {
|
||||
(fl!("add-image"), Message::ImageAddDialog)
|
||||
};
|
||||
|
||||
button::link(text)
|
||||
.trailing_icon(true)
|
||||
.on_press(message)
|
||||
.apply(cosmic::widget::container)
|
||||
.align_y(alignment::Vertical::Bottom)
|
||||
};
|
||||
let button = button::link(text).trailing_icon(true).on_press(message);
|
||||
|
||||
Some(button)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
children.push(
|
||||
row::with_capacity(2)
|
||||
.align_items(Alignment::Center)
|
||||
// Show a folder icon if the active category is a custom folder.
|
||||
.push_maybe(
|
||||
if let Some(Category::RecentFolder(_)) = page.categories.selected {
|
||||
Some(icon::from_name("folder-symbolic").size(16).icon())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
.push(category_selection)
|
||||
.push(cosmic::widget::horizontal_space(Length::Fill))
|
||||
.push(add_button)
|
||||
.push_maybe(add_button)
|
||||
.into(),
|
||||
);
|
||||
|
||||
match page.categories.selected {
|
||||
// Displays system wallpapers that are available to select from
|
||||
Some(Category::Backgrounds | Category::RecentFolder(_)) => {
|
||||
Some(Category::Wallpapers | Category::RecentFolder(_)) => {
|
||||
children.push(widgets::wallpaper_select_options(
|
||||
page,
|
||||
if let Choice::Background(selection) = page.selection.active {
|
||||
if let Choice::Wallpaper(selection) = page.selection.active {
|
||||
Some(selection)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
matches!(page.categories.selected, Some(Category::Wallpapers)),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -1044,7 +1111,7 @@ pub fn settings() -> Section<crate::pages::Message> {
|
|||
));
|
||||
}
|
||||
|
||||
None => (),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
cosmic::widget::column::with_children(children)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const COLUMN_SPACING: u16 = 12;
|
|||
const ROW_SPACING: u16 = 16;
|
||||
|
||||
/// A button for selecting a color or gradient.
|
||||
#[must_use]
|
||||
pub fn color_button(
|
||||
color: wallpaper::Color,
|
||||
removable: bool,
|
||||
|
|
@ -36,6 +37,7 @@ pub fn color_button(
|
|||
}
|
||||
|
||||
/// A sized container that's filled with a color or gradient.
|
||||
#[must_use]
|
||||
pub fn color_image<'a, M: 'a>(
|
||||
color: wallpaper::Color,
|
||||
width: u16,
|
||||
|
|
@ -78,6 +80,7 @@ pub fn color_image<'a, M: 'a>(
|
|||
}
|
||||
|
||||
/// Color selection list
|
||||
#[must_use]
|
||||
pub fn color_select_options(
|
||||
context: &super::Context,
|
||||
selected: Option<&wallpaper::Color>,
|
||||
|
|
@ -106,22 +109,26 @@ pub fn color_select_options(
|
|||
}
|
||||
|
||||
/// Background selection list
|
||||
#[must_use]
|
||||
pub fn wallpaper_select_options(
|
||||
page: &super::Page,
|
||||
selected: Option<DefaultKey>,
|
||||
show_custom_images: bool,
|
||||
) -> Element<Message> {
|
||||
let mut vec = Vec::with_capacity(page.selection.selection_handles.len());
|
||||
|
||||
// Place removable custom images first
|
||||
for id in page.selection.custom_images.iter().rev() {
|
||||
let handle = &page.selection.selection_handles[*id];
|
||||
if show_custom_images {
|
||||
// Place removable custom images first
|
||||
for id in page.selection.custom_images.iter().rev() {
|
||||
let handle = &page.selection.selection_handles[*id];
|
||||
|
||||
vec.push(wallpaper_button(
|
||||
handle,
|
||||
*id,
|
||||
true,
|
||||
selected.map_or(false, |selection| id == &selection),
|
||||
));
|
||||
vec.push(wallpaper_button(
|
||||
handle,
|
||||
*id,
|
||||
true,
|
||||
selected.map_or(false, |selection| id == &selection),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Then place non-removable images from the current folder
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ all-displays = Všechny monitory
|
|||
colors = Barvy
|
||||
fit-to-screen = Vyplnit obrazovku
|
||||
stretch = Roztáhnout
|
||||
system-backgrounds = Systémové pozadí
|
||||
zoom = Přiblížení
|
||||
|
||||
x-minutes = { $number } minut
|
||||
|
|
|
|||
|
|
@ -144,25 +144,26 @@ panel-missing = Panel Configuration is Missing
|
|||
## Desktop: Wallpaper
|
||||
|
||||
wallpaper = Wallpaper
|
||||
.desc = Background images, colors, and slideshow options.
|
||||
.same = Same background on all displays
|
||||
.fit = Background fit
|
||||
.slide = Slideshow
|
||||
.change = Change image every
|
||||
.desc = Wallpaper images, colors, and slideshow options.
|
||||
.fit = Wallpaper fit
|
||||
.folder-dialog = Choose wallpaper folder
|
||||
.image-dialog = Choose wallpaper image
|
||||
.plural = Wallpapers
|
||||
.same = Same wallpaper on all displays
|
||||
.slide = Slideshow
|
||||
|
||||
add-color = Add color
|
||||
add-image = Add image
|
||||
all-displays = All Displays
|
||||
colors = Colors
|
||||
dialog-add = _Add
|
||||
fit-to-screen = Fit to Screen
|
||||
open-new-folder = Open new folder
|
||||
recent-folders = Recent Folders
|
||||
stretch = Stretch
|
||||
system-backgrounds = System backgrounds
|
||||
zoom = Zoom
|
||||
|
||||
wallpaper-dialog-image = Choose wallpaper image
|
||||
.accept = _Add
|
||||
|
||||
x-minutes = { $number } minutes
|
||||
x-hours = { $number ->
|
||||
[1] 1 hour
|
||||
|
|
|
|||
|
|
@ -107,7 +107,6 @@ all-displays = Tutti gli Schermi
|
|||
colors = Colori
|
||||
fit-to-screen = Adatta allo Schermo
|
||||
stretch = Allarga
|
||||
system-backgrounds = Sfondi di sistema
|
||||
zoom = Zoom
|
||||
|
||||
x-minutes = { $number } minuti
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ all-displays = Все экраны
|
|||
colors = Цвета
|
||||
fit-to-screen = Подгонять под экран
|
||||
stretch = Растянуть
|
||||
system-backgrounds = Системные фоны
|
||||
zoom = Увеличить
|
||||
|
||||
x-minutes = { $number } минут
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ all-displays = Сви екрани
|
|||
colors = Боје
|
||||
fit-to-screen = Уклопи у екран
|
||||
stretch = Развуци
|
||||
system-backgrounds = Системске позадине
|
||||
zoom = Увећај
|
||||
|
||||
x-minutes = { $number } мин.
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ all-displays = Svi ekrani
|
|||
colors = Boje
|
||||
fit-to-screen = Uklopi u ekran
|
||||
stretch = Razvuci
|
||||
system-backgrounds = Sistemske pozadine
|
||||
zoom = Uvećaj
|
||||
|
||||
x-minutes = { $number } min.
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ all-displays = Tüm Ekranlar
|
|||
colors = Renkler
|
||||
fit-to-screen = Ekrana Sığdır
|
||||
stretch = Uzat
|
||||
system-backgrounds = Sistem duvar kağıtları
|
||||
zoom = Yakınlaştır
|
||||
|
||||
x-minutes = { $number } dakika
|
||||
|
|
|
|||
|
|
@ -148,7 +148,6 @@ all-displays = 所有顯示器
|
|||
colors = 顏色
|
||||
fit-to-screen = 延伸至全螢幕
|
||||
stretch = 延伸
|
||||
system-backgrounds = 系統背景
|
||||
zoom = 縮放
|
||||
|
||||
x-minutes = { $number } 分鐘
|
||||
|
|
|
|||
|
|
@ -69,12 +69,6 @@ pub fn config() -> (Config, HashMap<String, String>) {
|
|||
|
||||
pub fn set(config: &mut Config, entry: Entry) {
|
||||
if let Ok(context) = Config::helper() {
|
||||
tracing::debug!(
|
||||
output = entry.output.to_string(),
|
||||
source = ?entry.source,
|
||||
"setting wallpaper",
|
||||
);
|
||||
|
||||
let _res = Config::set_same_on_all(&context, config.same_on_all);
|
||||
|
||||
if let Err(why) = config.set_entry(&context, entry) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue