Implement menu side of watched status filtering
This commit is contained in:
parent
629f2ba9d0
commit
e1fbc92e08
10 changed files with 99 additions and 19 deletions
2
data/eye-closed-symbolic.svg
Normal file
2
data/eye-closed-symbolic.svg
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 6.703125 14 c -0.3125 -0.027344 -0.527344 -0.335938 -0.4375 -0.640625 l 0.425781 -1.542969 c -0.421875 -0.109375 -0.835937 -0.261718 -1.238281 -0.457031 l -1.019531 1.765625 c -0.09375 0.164062 -0.269532 0.261719 -0.457032 0.253906 c -0.382812 -0.011718 -0.605468 -0.429687 -0.410156 -0.757812 l 1.015625 -1.757813 c -0.335937 -0.214843 -0.664062 -0.449219 -0.976562 -0.703125 l -1.253907 1.253906 c -0.09375 0.097657 -0.222656 0.152344 -0.359374 0.152344 c -0.445313 -0.003906 -0.664063 -0.546875 -0.347657 -0.859375 l 1.222657 -1.21875 c -0.28125 -0.265625 -0.546876 -0.523437 -0.792969 -0.792969 l -0.722657 0.71875 c -0.09375 0.097657 -0.222656 0.152344 -0.359374 0.152344 c -0.445313 -0.003906 -0.664063 -0.546875 -0.347657 -0.859375 l 0.765625 -0.761719 c -0.886718 -1.078124 -1.410156 -1.945312 -1.410156 -1.945312 h 2 s 2.132812 4 6 4 s 6 -4 6 -4 h 2 s -0.523438 0.867188 -1.410156 1.945312 l 0.761718 0.761719 c 0.328126 0.320313 0.09375 0.871094 -0.363281 0.859375 c -0.128906 -0.003906 -0.25 -0.058594 -0.34375 -0.152344 l -0.71875 -0.71875 c -0.199219 0.21875 -0.410156 0.425782 -0.636719 0.644532 l 1.105469 1.414062 c 0.269531 0.335938 0.015625 0.835938 -0.417969 0.8125 c -0.144531 -0.007812 -0.28125 -0.082031 -0.371093 -0.199218 l -1.050781 -1.34375 c -0.261719 0.21875 -0.527344 0.429687 -0.808594 0.628906 l 1.070312 1.738281 c 0.21875 0.34375 -0.042968 0.789063 -0.449218 0.765625 c -0.164063 -0.007812 -0.3125 -0.097656 -0.398438 -0.242188 l -1.078125 -1.738281 c -0.363281 0.199219 -0.738281 0.371094 -1.125 0.503907 l 0.570313 1.648437 c 0.117187 0.320313 -0.117188 0.664063 -0.460938 0.671875 c -0.21875 0.003906 -0.414062 -0.136719 -0.484375 -0.34375 l -0.597656 -1.722656 c -0.257813 0.042968 -0.523438 0.066406 -0.792969 0.066406 c -0.105469 0 -0.207031 -0.019531 -0.3125 -0.027344 l -0.457031 1.652344 c -0.054688 0.21875 -0.25 0.371094 -0.476563 0.375 c -0.015625 0 -0.03125 0 -0.050781 0 z m 0 0" fill="#222222"/></svg>
|
||||||
|
After Width: | Height: | Size: 2 KiB |
|
|
@ -2,6 +2,8 @@
|
||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/com/kernelmaft/zoodex/">
|
<gresource prefix="/com/kernelmaft/zoodex/">
|
||||||
<file>application.css</file>
|
<file>application.css</file>
|
||||||
|
|
||||||
|
<file>eye-closed-symbolic.svg</file>
|
||||||
<file>eye-outline-filled-symbolic.svg</file>
|
<file>eye-outline-filled-symbolic.svg</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ impl SimpleComponent for CollatableFilmGrid {
|
||||||
FilmCollationMenuOutput::SortBy(sorting, direction) => {
|
FilmCollationMenuOutput::SortBy(sorting, direction) => {
|
||||||
FilmGridInput::SortBy(sorting, direction)
|
FilmGridInput::SortBy(sorting, direction)
|
||||||
}
|
}
|
||||||
|
FilmCollationMenuOutput::ApplyWatchedFilter(watched_filter) => {
|
||||||
|
FilmGridInput::ApplyWatchedFilter(watched_filter)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,35 @@
|
||||||
use gtk4::prelude::{
|
use gtk4::prelude::{
|
||||||
BoxExt, ButtonExt, EntryExt, ListBoxRowExt, ObjectExt, OrientableExt, PopoverExt, WidgetExt,
|
BoxExt, ButtonExt, EntryExt, ListBoxRowExt, ObjectExt, OrientableExt, PopoverExt,
|
||||||
|
ToggleButtonExt, WidgetExt,
|
||||||
};
|
};
|
||||||
use gtk4::{Align, Button, Entry, Label, ListBox, MenuButton, Orientation, Popover};
|
use gtk4::{Align, Button, Entry, Label, ListBox, MenuButton, Orientation, Popover, ToggleButton};
|
||||||
use relm4::{ComponentParts, ComponentSender, SimpleComponent, component};
|
use relm4::{ComponentParts, ComponentSender, SimpleComponent, component};
|
||||||
|
|
||||||
use crate::ui::components::sorting_popover_entry::sorting_popover_entry;
|
use crate::ui::components::sorting_popover_entry::sorting_popover_entry;
|
||||||
|
use crate::ui::filtering::WatchedFilter;
|
||||||
use crate::ui::sorting::{FilmsSorting, SortingDirection};
|
use crate::ui::sorting::{FilmsSorting, SortingDirection};
|
||||||
|
use crate::ui::widget_extensions::ComponentSenderExt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct FilmCollationMenu {
|
pub struct FilmCollationMenu {
|
||||||
sorted_by: FilmsSorting,
|
sorted_by: FilmsSorting,
|
||||||
sort_direction: SortingDirection,
|
sort_direction: SortingDirection,
|
||||||
|
watched_filter: Option<WatchedFilter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FilmCollationMenuInput {
|
pub enum FilmCollationMenuInput {
|
||||||
SortBy(FilmsSorting),
|
SortBy(FilmsSorting),
|
||||||
ToggleSortOrder,
|
ToggleSortOrder,
|
||||||
|
ToggleWatchedFilter,
|
||||||
|
ToggleUnwatchedFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FilmCollationMenuOutput {
|
pub enum FilmCollationMenuOutput {
|
||||||
SortBy(FilmsSorting, SortingDirection),
|
SortBy(FilmsSorting, SortingDirection),
|
||||||
|
ApplyWatchedFilter(Option<WatchedFilter>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component(pub)]
|
#[component(pub)]
|
||||||
|
|
@ -89,12 +96,33 @@ impl SimpleComponent for FilmCollationMenu {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
set_width_request: 230,
|
set_width_request: 230,
|
||||||
set_placeholder_text: Some("Search"),
|
set_placeholder_text: Some("Search"),
|
||||||
set_secondary_icon_name: Some("system-search-symbolic"),
|
set_secondary_icon_name: Some("system-search-symbolic"),
|
||||||
set_secondary_icon_sensitive: false,
|
set_secondary_icon_sensitive: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
gtk4::Box {
|
||||||
|
set_orientation: Orientation::Horizontal,
|
||||||
|
set_css_classes: &["linked"],
|
||||||
|
|
||||||
|
ToggleButton {
|
||||||
|
set_icon_name: "eye-outline-filled-symbolic",
|
||||||
|
#[watch]
|
||||||
|
#[block_signal(watched_toggled)]
|
||||||
|
set_active: model.watched_filter == Some(WatchedFilter::OnlyWatched),
|
||||||
|
connect_toggled => FilmCollationMenuInput::ToggleWatchedFilter @watched_toggled,
|
||||||
|
},
|
||||||
|
ToggleButton {
|
||||||
|
set_icon_name: "eye-closed-symbolic",
|
||||||
|
#[watch]
|
||||||
|
#[block_signal(unwatched_toggled)]
|
||||||
|
set_active: model.watched_filter == Some(WatchedFilter::OnlyUnwatched),
|
||||||
|
connect_toggled => FilmCollationMenuInput::ToggleUnwatchedFilter @unwatched_toggled,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,6 +134,7 @@ impl SimpleComponent for FilmCollationMenu {
|
||||||
let model = FilmCollationMenu {
|
let model = FilmCollationMenu {
|
||||||
sorted_by: FilmsSorting::Name,
|
sorted_by: FilmsSorting::Name,
|
||||||
sort_direction: SortingDirection::Ascending,
|
sort_direction: SortingDirection::Ascending,
|
||||||
|
watched_filter: None,
|
||||||
};
|
};
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
|
|
@ -120,7 +149,7 @@ impl SimpleComponent for FilmCollationMenu {
|
||||||
FilmCollationMenuInput::SortBy(sorting) => {
|
FilmCollationMenuInput::SortBy(sorting) => {
|
||||||
self.sorted_by = sorting;
|
self.sorted_by = sorting;
|
||||||
self.sort_direction = SortingDirection::Ascending;
|
self.sort_direction = SortingDirection::Ascending;
|
||||||
sender.output_sender().emit(FilmCollationMenuOutput::SortBy(
|
sender.emit_output(FilmCollationMenuOutput::SortBy(
|
||||||
sorting,
|
sorting,
|
||||||
SortingDirection::Ascending,
|
SortingDirection::Ascending,
|
||||||
));
|
));
|
||||||
|
|
@ -130,11 +159,37 @@ impl SimpleComponent for FilmCollationMenu {
|
||||||
SortingDirection::Ascending => SortingDirection::Descending,
|
SortingDirection::Ascending => SortingDirection::Descending,
|
||||||
SortingDirection::Descending => SortingDirection::Ascending,
|
SortingDirection::Descending => SortingDirection::Ascending,
|
||||||
};
|
};
|
||||||
sender.output_sender().emit(FilmCollationMenuOutput::SortBy(
|
sender.emit_output(FilmCollationMenuOutput::SortBy(
|
||||||
self.sorted_by,
|
self.sorted_by,
|
||||||
self.sort_direction,
|
self.sort_direction,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
FilmCollationMenuInput::ToggleWatchedFilter => {
|
||||||
|
match self.watched_filter {
|
||||||
|
Some(WatchedFilter::OnlyWatched) => {
|
||||||
|
self.watched_filter = None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.watched_filter = Some(WatchedFilter::OnlyWatched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sender.emit_output(FilmCollationMenuOutput::ApplyWatchedFilter(
|
||||||
|
self.watched_filter,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
FilmCollationMenuInput::ToggleUnwatchedFilter => {
|
||||||
|
match self.watched_filter {
|
||||||
|
Some(WatchedFilter::OnlyUnwatched) => {
|
||||||
|
self.watched_filter = None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.watched_filter = Some(WatchedFilter::OnlyUnwatched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sender.emit_output(FilmCollationMenuOutput::ApplyWatchedFilter(
|
||||||
|
self.watched_filter,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use relm4::{ComponentParts, ComponentSender, SimpleComponent, component};
|
||||||
|
|
||||||
use crate::ui::components::sorting_popover_entry::sorting_popover_entry;
|
use crate::ui::components::sorting_popover_entry::sorting_popover_entry;
|
||||||
use crate::ui::sorting::{SeriesSorting, SortingDirection};
|
use crate::ui::sorting::{SeriesSorting, SortingDirection};
|
||||||
|
use crate::ui::widget_extensions::ComponentSenderExt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,9 +119,7 @@ impl SimpleComponent for SeriesCollationMenu {
|
||||||
SeriesCollationMenuInput::SortBy(sorting) => {
|
SeriesCollationMenuInput::SortBy(sorting) => {
|
||||||
self.sorted_by = sorting;
|
self.sorted_by = sorting;
|
||||||
self.sort_direction = SortingDirection::Ascending;
|
self.sort_direction = SortingDirection::Ascending;
|
||||||
sender
|
sender.emit_output(SeriesCollationMenuOutput::SortBy(
|
||||||
.output_sender()
|
|
||||||
.emit(SeriesCollationMenuOutput::SortBy(
|
|
||||||
sorting,
|
sorting,
|
||||||
SortingDirection::Ascending,
|
SortingDirection::Ascending,
|
||||||
));
|
));
|
||||||
|
|
@ -130,9 +129,7 @@ impl SimpleComponent for SeriesCollationMenu {
|
||||||
SortingDirection::Ascending => SortingDirection::Descending,
|
SortingDirection::Ascending => SortingDirection::Descending,
|
||||||
SortingDirection::Descending => SortingDirection::Ascending,
|
SortingDirection::Descending => SortingDirection::Ascending,
|
||||||
};
|
};
|
||||||
sender
|
sender.emit_output(SeriesCollationMenuOutput::SortBy(
|
||||||
.output_sender()
|
|
||||||
.emit(SeriesCollationMenuOutput::SortBy(
|
|
||||||
self.sorted_by,
|
self.sorted_by,
|
||||||
self.sort_direction,
|
self.sort_direction,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use gtk4::{Align, Button, IconSize, Image, Justification, Label, Orientation, To
|
||||||
use relm4::{Component, ComponentParts, ComponentSender, RelmWidgetExt, component};
|
use relm4::{Component, ComponentParts, ComponentSender, RelmWidgetExt, component};
|
||||||
|
|
||||||
use crate::persist::data_manager::{DataManager, DataManagerError};
|
use crate::persist::data_manager::{DataManager, DataManagerError};
|
||||||
|
use crate::ui::widget_extensions::ComponentSenderExt;
|
||||||
use crate::views::overview::FilmOverview;
|
use crate::views::overview::FilmOverview;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -97,9 +98,7 @@ impl Component for FilmDetails {
|
||||||
match message {
|
match message {
|
||||||
FilmDetailsInput::WatchedStatusChanged(watched) => {
|
FilmDetailsInput::WatchedStatusChanged(watched) => {
|
||||||
self.film_overview.watched = watched;
|
self.film_overview.watched = watched;
|
||||||
sender
|
sender.emit_output(FilmDetailsOutput::WatchedStatusChanged(watched));
|
||||||
.output_sender()
|
|
||||||
.emit(FilmDetailsOutput::WatchedStatusChanged(watched));
|
|
||||||
|
|
||||||
sender.oneshot_command(clone!(
|
sender.oneshot_command(clone!(
|
||||||
#[strong(rename_to = uuid)]
|
#[strong(rename_to = uuid)]
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use relm4::{Component, ComponentParts, ComponentSender, component};
|
||||||
use crate::persist::data_manager::{DataManager, DataManagerError};
|
use crate::persist::data_manager::{DataManager, DataManagerError};
|
||||||
use crate::ui::components::media_grid_item::FilmGridItem;
|
use crate::ui::components::media_grid_item::FilmGridItem;
|
||||||
use crate::ui::factory_sorting::sort_factory_vec;
|
use crate::ui::factory_sorting::sort_factory_vec;
|
||||||
|
use crate::ui::filtering::WatchedFilter;
|
||||||
use crate::ui::sorting::{
|
use crate::ui::sorting::{
|
||||||
FilmsSorting, SortingDirection, cmp_films_by_name, cmp_films_by_rel_date, cmp_films_by_runtime,
|
FilmsSorting, SortingDirection, cmp_films_by_name, cmp_films_by_rel_date, cmp_films_by_runtime,
|
||||||
};
|
};
|
||||||
|
|
@ -20,6 +21,7 @@ pub struct FilmGrid {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FilmGridInput {
|
pub enum FilmGridInput {
|
||||||
SortBy(FilmsSorting, SortingDirection),
|
SortBy(FilmsSorting, SortingDirection),
|
||||||
|
ApplyWatchedFilter(Option<WatchedFilter>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -96,6 +98,7 @@ impl Component for FilmGrid {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
FilmGridInput::ApplyWatchedFilter(_watched_filter) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
src/ui/filtering.rs
Normal file
5
src/ui/filtering.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum WatchedFilter {
|
||||||
|
OnlyWatched,
|
||||||
|
OnlyUnwatched,
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod components;
|
mod components;
|
||||||
mod factory_sorting;
|
mod factory_sorting;
|
||||||
|
mod filtering;
|
||||||
mod sorting;
|
mod sorting;
|
||||||
mod widget_extensions;
|
mod widget_extensions;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use gtk4::prelude::{BoxExt, IsA};
|
||||||
use gtk4::{Label, Widget};
|
use gtk4::{Label, Widget};
|
||||||
use libadwaita::Dialog;
|
use libadwaita::Dialog;
|
||||||
use libadwaita::prelude::AdwDialogExt;
|
use libadwaita::prelude::AdwDialogExt;
|
||||||
|
use relm4::{Component, ComponentSender};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,3 +67,15 @@ impl AttrListExt for AttrList {
|
||||||
self.insert(AttrFontDesc::new(&font_desc));
|
self.insert(AttrFontDesc::new(&font_desc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub trait ComponentSenderExt<C: Component> {
|
||||||
|
fn emit_output(&self, message: C::Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: Component> ComponentSenderExt<C> for ComponentSender<C> {
|
||||||
|
fn emit_output(&self, message: C::Output) {
|
||||||
|
self.output_sender().emit(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue