h-gtk: Move vies inside the widgets module.
EpisodeView was renamed to HomeView. More renaming will follow.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
use gtk;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EmptyView {
|
||||
pub container: gtk::Box,
|
||||
}
|
||||
|
||||
impl Default for EmptyView {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui");
|
||||
let view: gtk::Box = builder.get_object("empty_view").unwrap();
|
||||
|
||||
EmptyView { container: view }
|
||||
}
|
||||
}
|
||||
|
||||
impl EmptyView {
|
||||
#[inline]
|
||||
pub fn new() -> EmptyView {
|
||||
EmptyView::default()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
use gtk;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Orientation::Vertical;
|
||||
use relm::{Relm, Update, Widget};
|
||||
|
||||
use chrono::prelude::*;
|
||||
|
||||
#[derive(Msg)]
|
||||
enum TitleMsg {
|
||||
Normal,
|
||||
GreyedOut,
|
||||
SetText(String),
|
||||
}
|
||||
|
||||
// Create the structure that holds the widgets used in the view.
|
||||
struct Title {
|
||||
title: gtk::Label,
|
||||
}
|
||||
|
||||
impl Update for Title {
|
||||
// Specify the model used for this widget.
|
||||
type Model = ();
|
||||
// Specify the model parameter used to init the model.
|
||||
type ModelParam = ();
|
||||
// Specify the type of the messages sent to the update function.
|
||||
type Msg = TitleMsg;
|
||||
|
||||
fn model(_: &Relm<Self>, _: ()) -> () {}
|
||||
|
||||
fn update(&mut self, event: TitleMsg) {
|
||||
match event {
|
||||
TitleMsg::Normal => {
|
||||
self.title
|
||||
.get_style_context()
|
||||
.map(|c| c.remove_class("dim-label"));
|
||||
}
|
||||
TitleMsg::GreyedOut => {
|
||||
self.title
|
||||
.get_style_context()
|
||||
.map(|c| c.add_class("dim-label"));
|
||||
}
|
||||
TitleMsg::SetText(s) => {
|
||||
self.title.set_text(&s);
|
||||
// self.title.set_tooltip_text(s.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Title {
|
||||
// Specify the type of the root widget.
|
||||
type Root = gtk::Label;
|
||||
|
||||
// Return the root widget.
|
||||
fn root(&self) -> Self::Root {
|
||||
self.title.clone()
|
||||
}
|
||||
|
||||
fn view(relm: &Relm<Self>, model: Self::Model) -> Self {
|
||||
let title = gtk::Label::new("Unkown Title");
|
||||
|
||||
Title { title }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Msg)]
|
||||
enum DateMsg {
|
||||
Usual,
|
||||
ShowYear,
|
||||
}
|
||||
|
||||
struct Date {
|
||||
date: gtk::Label,
|
||||
epoch: i64
|
||||
}
|
||||
|
||||
impl Update for Date {
|
||||
type Model = i64;
|
||||
type ModelParam = i64;
|
||||
type Msg = DateMsg;
|
||||
|
||||
fn model(_: &Relm<Self>, epoch: i64) -> i64 {
|
||||
epoch
|
||||
}
|
||||
|
||||
fn update(&mut self, event: DateMsg) {
|
||||
match event {
|
||||
DateMsg::Usual => {
|
||||
let ts = Utc.timestamp(self.epoch, 0);
|
||||
self.date.set_text(ts.format("%e %b").to_string().trim());
|
||||
}
|
||||
DateMsg::ShowYear => {
|
||||
let ts = Utc.timestamp(self.epoch, 0);
|
||||
self.date.set_text(ts.format("%e %b %Y").to_string().trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Date {
|
||||
type Root = gtk::Label;
|
||||
|
||||
fn root(&self) -> Self::Root {
|
||||
self.date.clone()
|
||||
}
|
||||
|
||||
fn view(relm: &Relm<Self>, model: Self::Model) -> Self {
|
||||
let date = gtk::Label::new("");
|
||||
|
||||
Date { date, epoch: model }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Msg)]
|
||||
enum DurationMsg {
|
||||
Show,
|
||||
Hide,
|
||||
SetDuration,
|
||||
}
|
||||
|
||||
struct Duration {
|
||||
duration: gtk::Label,
|
||||
separator: gtk::Label,
|
||||
seconds: Option<i32>,
|
||||
}
|
||||
|
||||
impl Update for Date {
|
||||
type Model = Option<i32>;
|
||||
type ModelParam = Option<i32>;
|
||||
type Msg = DateMsg;
|
||||
|
||||
fn model(_: &Relm<Self>, seconds: Option<i32>) -> Option<i32> {
|
||||
seconds
|
||||
}
|
||||
|
||||
fn update(&mut self, event: DateMsg) {
|
||||
match event {
|
||||
DurationMsg::Show => {
|
||||
self.duration.show();
|
||||
self.separator.show();
|
||||
}
|
||||
DurationMsg::Hide => {
|
||||
self.duration.hide();
|
||||
self.separator.hide();
|
||||
}
|
||||
DurationMsg::SetDuration => {
|
||||
let minutes = chrono::Duration::seconds(self.into()).num_minutes();
|
||||
if miutes == 0 {
|
||||
// FIXME: emit DurationMsg::Hide
|
||||
} else {
|
||||
// FIXME: emit DurationMsg::Show
|
||||
self.duration.set_text(&format!("{} min", minutes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Date {
|
||||
// FIXME: This is weird
|
||||
type Root = gtk::Label;
|
||||
|
||||
fn root(&self) -> Self::Root {
|
||||
self.date.clone()
|
||||
}
|
||||
|
||||
fn view(relm: &Relm<Self>, model: Self::Model) -> Self {
|
||||
let date = gtk::Label::new("");
|
||||
|
||||
Date { date, epoch: model }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// struct Model {
|
||||
// counter: i32,
|
||||
// }
|
||||
|
||||
// #[derive(Msg)]
|
||||
// enum Msg {
|
||||
// Decrement,
|
||||
// Increment,
|
||||
// }
|
||||
|
||||
// Create the structure that holds the widgets used in the view.
|
||||
// struct EpisodeWidgetRelm {
|
||||
// model: Model,
|
||||
|
||||
// container: gtk::Box,
|
||||
// progress: gtk::ProgressBar,
|
||||
|
||||
// download: gtk::Button,
|
||||
// play: gtk::Button,
|
||||
// cancel: gtk::Button,
|
||||
|
||||
// title: gtk::Label,
|
||||
// date: gtk::Label,
|
||||
// duration: gtk::Label,
|
||||
// local_size: gtk::Label,
|
||||
// total_size: gtk::Label,
|
||||
|
||||
// separator1: gtk::Label,
|
||||
// separator2: gtk::Label,
|
||||
// prog_separator: gtk::Label,
|
||||
// }
|
||||
|
||||
// impl Update for EpisodeWidgetRelm {
|
||||
// Specify the model used for this widget.
|
||||
// type Model = Model;
|
||||
// Specify the model parameter used to init the model.
|
||||
// type ModelParam = ();
|
||||
// Specify the type of the messages sent to the update function.
|
||||
// type Msg = Msg;
|
||||
|
||||
// fn model(_: &Relm<Self>, _: ()) -> Model {
|
||||
// Model { counter: 0 }
|
||||
// }
|
||||
|
||||
// fn update(&mut self, event: Msg) {
|
||||
// match event {
|
||||
// Msg::Decrement => {}
|
||||
// Msg::Increment => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl Widget for EpisodeWidgetRelm {
|
||||
// Specify the type of the root widget.
|
||||
// type Root = gtk::Box;
|
||||
|
||||
// Return the root widget.
|
||||
// fn root(&self) -> Self::Root {
|
||||
// self.container.clone()
|
||||
// }
|
||||
|
||||
// fn view(relm: &Relm<Self>, model: Self::Model) -> Self {
|
||||
// let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
|
||||
|
||||
// let container: gtk::Box = builder.get_object("episode_container").unwrap();
|
||||
// let progress: gtk::ProgressBar = builder.get_object("progress_bar").unwrap();
|
||||
|
||||
// let download: gtk::Button = builder.get_object("download_button").unwrap();
|
||||
// let play: gtk::Button = builder.get_object("play_button").unwrap();
|
||||
// let cancel: gtk::Button = builder.get_object("cancel_button").unwrap();
|
||||
|
||||
// let title: gtk::Label = builder.get_object("title_label").unwrap();
|
||||
// let date: gtk::Label = builder.get_object("date_label").unwrap();
|
||||
// let duration: gtk::Label = builder.get_object("duration_label").unwrap();
|
||||
// let local_size: gtk::Label = builder.get_object("local_size").unwrap();
|
||||
// let total_size: gtk::Label = builder.get_object("total_size").unwrap();
|
||||
|
||||
// let separator1: gtk::Label = builder.get_object("separator1").unwrap();
|
||||
// let separator2: gtk::Label = builder.get_object("separator2").unwrap();
|
||||
// let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap();
|
||||
|
||||
// Send the message Increment when the button is clicked.
|
||||
// connect!(relm, plus_button, connect_clicked(_), Msg::Increment);
|
||||
// connect!(relm, minus_button, connect_clicked(_), Msg::Decrement);
|
||||
|
||||
// EpisodeWidgetRelm {
|
||||
// model,
|
||||
// container,
|
||||
// progress,
|
||||
|
||||
// download,
|
||||
// play,
|
||||
// cancel,
|
||||
|
||||
// title,
|
||||
// date,
|
||||
// duration,
|
||||
// local_size,
|
||||
// total_size,
|
||||
|
||||
// separator1,
|
||||
// separator2,
|
||||
// prog_separator,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,236 @@
|
||||
use chrono::prelude::*;
|
||||
use failure::Error;
|
||||
use gtk;
|
||||
use gtk::prelude::*;
|
||||
|
||||
use hammond_data::dbqueries;
|
||||
use hammond_data::EpisodeWidgetQuery;
|
||||
use send_cell::SendCell;
|
||||
|
||||
use app::Action;
|
||||
use utils::lazy_load_full;
|
||||
use utils::{get_ignored_shows, set_image_from_path};
|
||||
use widgets::EpisodeWidget;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref EPISODES_VIEW_VALIGNMENT: Mutex<Option<SendCell<gtk::Adjustment>>> =
|
||||
Mutex::new(None);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum ListSplit {
|
||||
Today,
|
||||
Yday,
|
||||
Week,
|
||||
Month,
|
||||
Rest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HomeView {
|
||||
pub container: gtk::Box,
|
||||
scrolled_window: gtk::ScrolledWindow,
|
||||
frame_parent: gtk::Box,
|
||||
today_box: gtk::Box,
|
||||
yday_box: gtk::Box,
|
||||
week_box: gtk::Box,
|
||||
month_box: gtk::Box,
|
||||
rest_box: gtk::Box,
|
||||
today_list: gtk::ListBox,
|
||||
yday_list: gtk::ListBox,
|
||||
week_list: gtk::ListBox,
|
||||
month_list: gtk::ListBox,
|
||||
rest_list: gtk::ListBox,
|
||||
}
|
||||
|
||||
impl Default for HomeView {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episodes_view.ui");
|
||||
let container: gtk::Box = builder.get_object("container").unwrap();
|
||||
let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap();
|
||||
let frame_parent: gtk::Box = builder.get_object("frame_parent").unwrap();
|
||||
let today_box: gtk::Box = builder.get_object("today_box").unwrap();
|
||||
let yday_box: gtk::Box = builder.get_object("yday_box").unwrap();
|
||||
let week_box: gtk::Box = builder.get_object("week_box").unwrap();
|
||||
let month_box: gtk::Box = builder.get_object("month_box").unwrap();
|
||||
let rest_box: gtk::Box = builder.get_object("rest_box").unwrap();
|
||||
let today_list: gtk::ListBox = builder.get_object("today_list").unwrap();
|
||||
let yday_list: gtk::ListBox = builder.get_object("yday_list").unwrap();
|
||||
let week_list: gtk::ListBox = builder.get_object("week_list").unwrap();
|
||||
let month_list: gtk::ListBox = builder.get_object("month_list").unwrap();
|
||||
let rest_list: gtk::ListBox = builder.get_object("rest_list").unwrap();
|
||||
|
||||
HomeView {
|
||||
container,
|
||||
scrolled_window,
|
||||
frame_parent,
|
||||
today_box,
|
||||
yday_box,
|
||||
week_box,
|
||||
month_box,
|
||||
rest_box,
|
||||
today_list,
|
||||
yday_list,
|
||||
week_list,
|
||||
month_list,
|
||||
rest_list,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: REFACTOR ME
|
||||
impl HomeView {
|
||||
#[inline]
|
||||
pub fn new(sender: Sender<Action>) -> Result<Rc<HomeView>, Error> {
|
||||
use self::ListSplit::*;
|
||||
|
||||
let view = Rc::new(HomeView::default());
|
||||
let ignore = get_ignored_shows()?;
|
||||
let episodes = dbqueries::get_episodes_widgets_filter_limit(&ignore, 100)?;
|
||||
let now_utc = Utc::now();
|
||||
|
||||
let view_ = view.clone();
|
||||
let func = move |ep: EpisodeWidgetQuery| {
|
||||
let epoch = ep.epoch();
|
||||
let widget = EpisodesViewWidget::new(ep, sender.clone());
|
||||
|
||||
match split(&now_utc, i64::from(epoch)) {
|
||||
Today => add_to_box(&widget, &view_.today_list, &view_.today_box),
|
||||
Yday => add_to_box(&widget, &view_.yday_list, &view_.yday_box),
|
||||
Week => add_to_box(&widget, &view_.week_list, &view_.week_box),
|
||||
Month => add_to_box(&widget, &view_.month_list, &view_.month_box),
|
||||
Rest => add_to_box(&widget, &view_.rest_list, &view_.rest_box),
|
||||
}
|
||||
};
|
||||
|
||||
let view_ = view.clone();
|
||||
let callback = move || {
|
||||
view_
|
||||
.set_vadjustment()
|
||||
.map_err(|err| format!("{}", err))
|
||||
.ok();
|
||||
};
|
||||
|
||||
lazy_load_full(episodes, func, callback);
|
||||
view.container.show_all();
|
||||
Ok(view)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Set scrolled window vertical adjustment.
|
||||
fn set_vadjustment(&self) -> Result<(), Error> {
|
||||
let guard = EPISODES_VIEW_VALIGNMENT
|
||||
.lock()
|
||||
.map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?;
|
||||
|
||||
if let Some(ref sendcell) = *guard {
|
||||
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
||||
sendcell
|
||||
.try_get()
|
||||
.map(|x| self.scrolled_window.set_vadjustment(&x));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Save the vertical scrollbar position.
|
||||
pub fn save_alignment(&self) -> Result<(), Error> {
|
||||
if let Ok(mut guard) = EPISODES_VIEW_VALIGNMENT.lock() {
|
||||
let adj = self.scrolled_window
|
||||
.get_vadjustment()
|
||||
.ok_or_else(|| format_err!("Could not get the adjustment"))?;
|
||||
*guard = Some(SendCell::new(adj));
|
||||
info!("Saved episodes_view alignment.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_to_box(widget: &EpisodesViewWidget, listbox: >k::ListBox, box_: >k::Box) {
|
||||
listbox.add(&widget.container);
|
||||
box_.show();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn split(now: &DateTime<Utc>, epoch: i64) -> ListSplit {
|
||||
let ep = Utc.timestamp(epoch, 0);
|
||||
|
||||
if now.ordinal() == ep.ordinal() && now.year() == ep.year() {
|
||||
ListSplit::Today
|
||||
} else if now.ordinal() == ep.ordinal() + 1 && now.year() == ep.year() {
|
||||
ListSplit::Yday
|
||||
} else if now.iso_week().week() == ep.iso_week().week() && now.year() == ep.year() {
|
||||
ListSplit::Week
|
||||
} else if now.month() == ep.month() && now.year() == ep.year() {
|
||||
ListSplit::Month
|
||||
} else {
|
||||
ListSplit::Rest
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct EpisodesViewWidget {
|
||||
container: gtk::Box,
|
||||
image: gtk::Image,
|
||||
episode: gtk::Box,
|
||||
}
|
||||
|
||||
impl Default for EpisodesViewWidget {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let builder =
|
||||
gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episodes_view_widget.ui");
|
||||
let container: gtk::Box = builder.get_object("container").unwrap();
|
||||
let image: gtk::Image = builder.get_object("cover").unwrap();
|
||||
let ep = EpisodeWidget::default();
|
||||
container.pack_start(&ep.container, true, true, 6);
|
||||
|
||||
EpisodesViewWidget {
|
||||
container,
|
||||
image,
|
||||
episode: ep.container,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EpisodesViewWidget {
|
||||
fn new(episode: EpisodeWidgetQuery, sender: Sender<Action>) -> EpisodesViewWidget {
|
||||
let builder =
|
||||
gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episodes_view_widget.ui");
|
||||
let container: gtk::Box = builder.get_object("container").unwrap();
|
||||
let image: gtk::Image = builder.get_object("cover").unwrap();
|
||||
let pid = episode.podcast_id();
|
||||
let ep = EpisodeWidget::new(episode, sender.clone());
|
||||
|
||||
let view = EpisodesViewWidget {
|
||||
container,
|
||||
image,
|
||||
episode: ep.container,
|
||||
};
|
||||
|
||||
view.init(pid);
|
||||
view
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn init(&self, podcast_id: i32) {
|
||||
self.set_cover(podcast_id)
|
||||
.map_err(|err| error!("Failed to set a cover: {}", err))
|
||||
.ok();
|
||||
|
||||
self.container.pack_start(&self.episode, true, true, 6);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_cover(&self, podcast_id: i32) -> Result<(), Error> {
|
||||
set_image_from_path(&self.image, podcast_id, 64)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,13 @@
|
||||
mod empty;
|
||||
mod episode;
|
||||
mod episode_states;
|
||||
mod home;
|
||||
mod show;
|
||||
mod shows;
|
||||
|
||||
pub use self::empty::EmptyView;
|
||||
pub use self::episode::EpisodeWidget;
|
||||
pub use self::home::HomeView;
|
||||
pub use self::show::ShowWidget;
|
||||
pub use self::show::{mark_all_notif, remove_show_notif};
|
||||
pub use self::shows::ShowsPopulated;
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
use failure::Error;
|
||||
use gtk;
|
||||
use gtk::prelude::*;
|
||||
|
||||
use hammond_data::dbqueries;
|
||||
use hammond_data::Podcast;
|
||||
|
||||
use app::Action;
|
||||
use utils::{get_ignored_shows, lazy_load, set_image_from_path};
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShowsPopulated {
|
||||
pub container: gtk::Box,
|
||||
scrolled_window: gtk::ScrolledWindow,
|
||||
flowbox: gtk::FlowBox,
|
||||
}
|
||||
|
||||
impl Default for ShowsPopulated {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_view.ui");
|
||||
let container: gtk::Box = builder.get_object("fb_parent").unwrap();
|
||||
let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap();
|
||||
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
||||
|
||||
ShowsPopulated {
|
||||
container,
|
||||
scrolled_window,
|
||||
flowbox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowsPopulated {
|
||||
#[inline]
|
||||
pub fn new(sender: Sender<Action>) -> Result<Rc<ShowsPopulated>, Error> {
|
||||
let pop = Rc::new(ShowsPopulated::default());
|
||||
pop.init(sender)?;
|
||||
Ok(pop)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init(&self, sender: Sender<Action>) -> Result<(), Error> {
|
||||
self.flowbox.connect_child_activated(move |_, child| {
|
||||
on_child_activate(child, sender.clone())
|
||||
.map_err(|err| error!("Error along flowbox child activation: {}", err))
|
||||
.ok();
|
||||
});
|
||||
// Populate the flowbox with the Podcasts.
|
||||
self.populate_flowbox()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn populate_flowbox(&self) -> Result<(), Error> {
|
||||
let ignore = get_ignored_shows()?;
|
||||
let podcasts = dbqueries::get_podcasts_filter(&ignore)?;
|
||||
|
||||
let flowbox = self.flowbox.clone();
|
||||
let constructor = |parent| ShowsChild::new(&parent).child;
|
||||
let callback = move || flowbox.show_all();
|
||||
|
||||
let flowbox = self.flowbox.clone();
|
||||
lazy_load(podcasts, flowbox, constructor, callback);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn on_child_activate(child: >k::FlowBoxChild, sender: Sender<Action>) -> Result<(), Error> {
|
||||
use gtk::WidgetExt;
|
||||
|
||||
// This is such an ugly hack...
|
||||
let id = WidgetExt::get_name(child)
|
||||
.ok_or_else(|| format_err!("Faild to get \"episodes\" child from the stack."))?
|
||||
.parse::<i32>()?;
|
||||
let pd = Arc::new(dbqueries::get_podcast_from_id(id)?);
|
||||
|
||||
sender.send(Action::HeaderBarShowTile(pd.title().into()))?;
|
||||
sender.send(Action::ReplaceWidget(pd))?;
|
||||
sender.send(Action::ShowWidgetAnimated)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ShowsChild {
|
||||
container: gtk::Box,
|
||||
cover: gtk::Image,
|
||||
child: gtk::FlowBoxChild,
|
||||
}
|
||||
|
||||
impl Default for ShowsChild {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_child.ui");
|
||||
|
||||
let container: gtk::Box = builder.get_object("fb_child").unwrap();
|
||||
let cover: gtk::Image = builder.get_object("pd_cover").unwrap();
|
||||
|
||||
let child = gtk::FlowBoxChild::new();
|
||||
child.add(&container);
|
||||
|
||||
ShowsChild {
|
||||
container,
|
||||
cover,
|
||||
child,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowsChild {
|
||||
#[inline]
|
||||
pub fn new(pd: &Podcast) -> ShowsChild {
|
||||
let child = ShowsChild::default();
|
||||
child.init(pd);
|
||||
child
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn init(&self, pd: &Podcast) {
|
||||
self.container.set_tooltip_text(pd.title());
|
||||
WidgetExt::set_name(&self.child, &pd.id().to_string());
|
||||
|
||||
self.set_cover(pd.id())
|
||||
.map_err(|err| error!("Failed to set a cover: {}", err))
|
||||
.ok();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_cover(&self, podcast_id: i32) -> Result<(), Error> {
|
||||
set_image_from_path(&self.cover, podcast_id, 256)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user