Merge branch 'show_widget_redesign' into 'master'
Show widget redesign See merge request alatiera/Hammond!6
This commit is contained in:
commit
3cbda5979d
@ -50,7 +50,7 @@ pub fn get_played_episodes() -> Result<Vec<Episode>> {
|
|||||||
Ok(episode.filter(played.is_not_null()).load::<Episode>(&*con)?)
|
Ok(episode.filter(played.is_not_null()).load::<Episode>(&*con)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_episode_from_id(ep_id: i32) -> Result<Episode> {
|
pub fn get_episode_from_rowid(ep_id: i32) -> Result<Episode> {
|
||||||
use schema::episode::dsl::*;
|
use schema::episode::dsl::*;
|
||||||
|
|
||||||
let db = connection();
|
let db = connection();
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use std::io::{BufWriter, Read, Write};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use errors::*;
|
use errors::*;
|
||||||
use hammond_data::{Episode, EpisodeWidgetQuery, Podcast};
|
use hammond_data::{EpisodeWidgetQuery, Podcast};
|
||||||
use hammond_data::xdg_dirs::{DL_DIR, HAMMOND_CACHE};
|
use hammond_data::xdg_dirs::{DL_DIR, HAMMOND_CACHE};
|
||||||
|
|
||||||
// TODO: Replace path that are of type &str with std::path.
|
// TODO: Replace path that are of type &str with std::path.
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<property name="spacing">5</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@ -28,8 +27,9 @@
|
|||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">start</property>
|
<property name="halign">start</property>
|
||||||
<property name="label" translatable="yes">Episode Title</property>
|
<property name="label" translatable="yes">Episode Title</property>
|
||||||
<property name="wrap">True</property>
|
|
||||||
<property name="ellipsize">end</property>
|
<property name="ellipsize">end</property>
|
||||||
|
<property name="single_line_mode">True</property>
|
||||||
|
<property name="max_width_chars">60</property>
|
||||||
<property name="track_visited_links">False</property>
|
<property name="track_visited_links">False</property>
|
||||||
<property name="lines">1</property>
|
<property name="lines">1</property>
|
||||||
</object>
|
</object>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
@ -135,14 +135,14 @@
|
|||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
@ -162,7 +162,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">False</property>
|
||||||
<property name="pack_type">end</property>
|
<property name="pack_type">end</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
@ -237,13 +237,15 @@
|
|||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">5</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
|||||||
@ -190,27 +190,6 @@
|
|||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="ref_button">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="always_show_image">True</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkImage">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="icon_name">view-refresh-symbolic</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="pack_type">end</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuButton" id="menu">
|
<object class="GtkMenuButton" id="menu">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|||||||
@ -2,191 +2,239 @@
|
|||||||
<!-- Generated with glade 3.20.2 -->
|
<!-- Generated with glade 3.20.2 -->
|
||||||
<interface domain="gnome-music">
|
<interface domain="gnome-music">
|
||||||
<requires lib="gtk+" version="3.12"/>
|
<requires lib="gtk+" version="3.12"/>
|
||||||
<object class="GtkBox" id="podcast_widget">
|
<object class="GtkBox" id="container">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkScrolledWindow">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="halign">center</property>
|
<property name="shadow_type">in</property>
|
||||||
<property name="valign">center</property>
|
|
||||||
<property name="margin_left">32</property>
|
|
||||||
<property name="margin_right">32</property>
|
|
||||||
<property name="margin_start">32</property>
|
|
||||||
<property name="margin_end">32</property>
|
|
||||||
<property name="margin_top">64</property>
|
|
||||||
<property name="margin_bottom">32</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkViewport">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">15</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkImage" id="cover">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">center</property>
|
|
||||||
<property name="valign">start</property>
|
|
||||||
<property name="margin_left">1</property>
|
|
||||||
<property name="margin_right">1</property>
|
|
||||||
<property name="margin_start">1</property>
|
|
||||||
<property name="margin_end">1</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
<property name="orientation">vertical</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="title_label">
|
<placeholder/>
|
||||||
<property name="width_request">50</property>
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="width_request">600</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
<property name="label_xalign">0</property>
|
||||||
<property name="label" translatable="yes">Foobar</property>
|
<property name="shadow_type">none</property>
|
||||||
<property name="use_markup">True</property>
|
<child>
|
||||||
<property name="justify">center</property>
|
<object class="GtkBox">
|
||||||
<property name="wrap">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="max_width_chars">28</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="track_visited_links">False</property>
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="spacing">10</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="cover">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="pixel_size">128</property>
|
||||||
|
<property name="icon_name">image-x-generic-symbolic</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">10</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuButton" id="settings_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="icon_name">emblem-system-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="link_button">
|
||||||
|
<property name="label" translatable="yes">Website</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">5</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="unsub_button">
|
||||||
|
<property name="label" translatable="yes">Unsubscribe</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">5</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="description">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="label" translatable="yes">Show description</property>
|
||||||
|
<property name="wrap">True</property>
|
||||||
|
<property name="wrap_mode">word-char</property>
|
||||||
|
<property name="max_width_chars">55</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="medium"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child type="label_item">
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">25</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame" id="episodes">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label_xalign">0</property>
|
||||||
|
<property name="shadow_type">in</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child type="label_item">
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="unsub_button">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="orientation">vertical</property>
|
||||||
<property name="halign">center</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage">
|
<placeholder/>
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="tooltip_text" translatable="yes">Unsubrscribe from this Podcast.
|
|
||||||
Warn: This will delete downloaded content associated with this Podcast.</property>
|
|
||||||
<property name="icon_name">user-trash-symbolic</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">True</property>
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="padding">5</property>
|
|
||||||
<property name="pack_type">end</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="mark_all_played_button">
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
<property name="tooltip_text" translatable="yes">Mark all episodes as Played.</property>
|
|
||||||
<property name="halign">center</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkImage">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="icon_name">object-select-symbolic</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
<property name="fill">False</property>
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkScrolledWindow">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="shadow_type">in</property>
|
|
||||||
<property name="min_content_width">200</property>
|
|
||||||
<property name="max_content_width">200</property>
|
|
||||||
<property name="propagate_natural_width">True</property>
|
|
||||||
<property name="propagate_natural_height">True</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkTextView" id="desc_text_view">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="editable">False</property>
|
|
||||||
<property name="wrap_mode">word-char</property>
|
|
||||||
<property name="cursor_visible">False</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">True</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkScrolledWindow">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="hexpand">True</property>
|
|
||||||
<property name="vexpand">True</property>
|
|
||||||
<property name="hscrollbar_policy">never</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkViewport" id="view">
|
|
||||||
<property name="width_request">400</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="shadow_type">none</property>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
@ -194,7 +242,7 @@ Warn: This will delete downloaded content associated with this Podcast.</propert
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">2</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|||||||
@ -60,8 +60,8 @@ impl ShowStack {
|
|||||||
header: header.clone(),
|
header: header.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let pop = ShowsPopulated::new_initialized(show.clone(), header);
|
let pop = ShowsPopulated::new(show.clone(), header);
|
||||||
let widget = ShowWidget::new();
|
let widget = ShowWidget::default();
|
||||||
let empty = EmptyView::new();
|
let empty = EmptyView::new();
|
||||||
|
|
||||||
show.stack.add_named(&pop.container, "podcasts");
|
show.stack.add_named(&pop.container, "podcasts");
|
||||||
@ -90,7 +90,7 @@ impl ShowStack {
|
|||||||
let vis = self.stack.get_visible_child_name().unwrap();
|
let vis = self.stack.get_visible_child_name().unwrap();
|
||||||
let old = self.stack.get_child_by_name("podcasts").unwrap();
|
let old = self.stack.get_child_by_name("podcasts").unwrap();
|
||||||
|
|
||||||
let pop = ShowsPopulated::new();
|
let pop = ShowsPopulated::default();
|
||||||
pop.init(Rc::new(self.clone()), self.header.clone());
|
pop.init(Rc::new(self.clone()), self.header.clone());
|
||||||
|
|
||||||
self.stack.remove(&old);
|
self.stack.remove(&old);
|
||||||
@ -109,7 +109,7 @@ impl ShowStack {
|
|||||||
|
|
||||||
pub fn replace_widget(&self, pd: &Podcast) {
|
pub fn replace_widget(&self, pd: &Podcast) {
|
||||||
let old = self.stack.get_child_by_name("widget").unwrap();
|
let old = self.stack.get_child_by_name("widget").unwrap();
|
||||||
let new = ShowWidget::new_initialized(Rc::new(self.clone()), self.header.clone(), pd);
|
let new = ShowWidget::new(Rc::new(self.clone()), self.header.clone(), pd);
|
||||||
|
|
||||||
self.stack.remove(&old);
|
self.stack.remove(&old);
|
||||||
self.stack.add_named(&new.container, "widget");
|
self.stack.add_named(&new.container, "widget");
|
||||||
|
|||||||
@ -12,19 +12,17 @@ use content::Content;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub container: gtk::HeaderBar,
|
pub container: gtk::HeaderBar,
|
||||||
refresh: gtk::Button,
|
|
||||||
add_toggle: gtk::MenuButton,
|
add_toggle: gtk::MenuButton,
|
||||||
switch: gtk::StackSwitcher,
|
switch: gtk::StackSwitcher,
|
||||||
back_button: gtk::Button,
|
back_button: gtk::Button,
|
||||||
show_title: gtk::Label,
|
show_title: gtk::Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Header {
|
impl Default for Header {
|
||||||
pub fn new() -> Rc<Header> {
|
fn default() -> Header {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
|
||||||
|
|
||||||
let header: gtk::HeaderBar = builder.get_object("headerbar").unwrap();
|
let header: gtk::HeaderBar = builder.get_object("headerbar").unwrap();
|
||||||
let refresh: gtk::Button = builder.get_object("ref_button").unwrap();
|
|
||||||
let add_toggle: gtk::MenuButton = builder.get_object("add_toggle_button").unwrap();
|
let add_toggle: gtk::MenuButton = builder.get_object("add_toggle_button").unwrap();
|
||||||
let switch: gtk::StackSwitcher = builder.get_object("switch").unwrap();
|
let switch: gtk::StackSwitcher = builder.get_object("switch").unwrap();
|
||||||
let back_button: gtk::Button = builder.get_object("back_button").unwrap();
|
let back_button: gtk::Button = builder.get_object("back_button").unwrap();
|
||||||
@ -33,14 +31,22 @@ impl Header {
|
|||||||
switch.set_halign(gtk::Align::Center);
|
switch.set_halign(gtk::Align::Center);
|
||||||
switch.show();
|
switch.show();
|
||||||
|
|
||||||
Rc::new(Header {
|
Header {
|
||||||
container: header,
|
container: header,
|
||||||
refresh,
|
|
||||||
add_toggle,
|
add_toggle,
|
||||||
switch,
|
switch,
|
||||||
back_button,
|
back_button,
|
||||||
show_title,
|
show_title,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Header {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new(content: Rc<Content>) -> Rc<Header> {
|
||||||
|
let h = Header::default();
|
||||||
|
h.init(content);
|
||||||
|
Rc::new(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&self, content: Rc<Content>) {
|
pub fn init(&self, content: Rc<Content>) {
|
||||||
@ -64,11 +70,6 @@ impl Header {
|
|||||||
}));
|
}));
|
||||||
self.add_toggle.set_popover(&add_popover);
|
self.add_toggle.set_popover(&add_popover);
|
||||||
|
|
||||||
// FIXME: There appears to be a memmory leak here.
|
|
||||||
self.refresh.connect_clicked(clone!(content => move |_| {
|
|
||||||
utils::refresh_feed(content.clone(), None, None);
|
|
||||||
}));
|
|
||||||
|
|
||||||
let switch = &self.switch;
|
let switch = &self.switch;
|
||||||
let add_toggle = &self.add_toggle;
|
let add_toggle = &self.add_toggle;
|
||||||
let show_title = &self.show_title;
|
let show_title = &self.show_title;
|
||||||
@ -87,7 +88,7 @@ impl Header {
|
|||||||
self.switch.hide();
|
self.switch.hide();
|
||||||
self.add_toggle.hide();
|
self.add_toggle.hide();
|
||||||
self.back_button.show();
|
self.back_button.show();
|
||||||
self.show_title.set_text(title);
|
self.set_show_title(title);
|
||||||
self.show_title.show();
|
self.show_title.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,9 +99,9 @@ impl Header {
|
|||||||
self.show_title.hide();
|
self.show_title.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn set_show_title(&self, title: &str) {
|
pub fn set_show_title(&self, title: &str) {
|
||||||
// self.show_title.set_text(title)
|
self.show_title.set_text(title)
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_add_bttn_clicked(content: Rc<Content>, entry: >k::Entry) {
|
fn on_add_bttn_clicked(content: Rc<Content>, entry: >k::Entry) {
|
||||||
@ -111,7 +112,7 @@ fn on_add_bttn_clicked(content: Rc<Content>, entry: >k::Entry) {
|
|||||||
if let Ok(s) = source {
|
if let Ok(s) = source {
|
||||||
info!("{:?} feed added", url);
|
info!("{:?} feed added", url);
|
||||||
// update the db
|
// update the db
|
||||||
utils::refresh_feed(content, Some(vec![s]), None);
|
utils::refresh_feed(content, Some(vec![s]));
|
||||||
} else {
|
} else {
|
||||||
error!("Feed probably already exists.");
|
error!("Feed probably already exists.");
|
||||||
error!("Error: {:?}", source.unwrap_err());
|
error!("Error: {:?}", source.unwrap_err());
|
||||||
|
|||||||
@ -24,6 +24,7 @@ use hammond_data::utils::checkup;
|
|||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt};
|
use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
// http://gtk-rs.org/tuto/closures
|
// http://gtk-rs.org/tuto/closures
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -52,28 +53,19 @@ mod content;
|
|||||||
mod utils;
|
mod utils;
|
||||||
mod static_resource;
|
mod static_resource;
|
||||||
|
|
||||||
/*
|
|
||||||
THIS IS STILL A PROTOTYPE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn build_ui(app: >k::Application) {
|
fn build_ui(app: >k::Application) {
|
||||||
let menu = gio::Menu::new();
|
let menu = gio::Menu::new();
|
||||||
menu.append("Quit", "app.quit");
|
menu.append("Quit", "app.quit");
|
||||||
menu.append("Checkup", "app.check");
|
menu.append("Checkup", "app.check");
|
||||||
|
menu.append("Update feeds", "app.update");
|
||||||
app.set_app_menu(&menu);
|
app.set_app_menu(&menu);
|
||||||
|
|
||||||
// Get the main window
|
// Get the main window
|
||||||
let window = gtk::ApplicationWindow::new(app);
|
let window = gtk::ApplicationWindow::new(app);
|
||||||
window.set_default_size(1150, 650);
|
window.set_default_size(1150, 650);
|
||||||
|
|
||||||
// TODO: this will blow horribly
|
|
||||||
// let ct = content::ContentState::new().unwrap();
|
|
||||||
// let stack = ct.get_stack();
|
|
||||||
|
|
||||||
// let ct = content::Content::new_initialized();
|
|
||||||
|
|
||||||
// Get the headerbar
|
// Get the headerbar
|
||||||
let header = headerbar::Header::new();
|
let header = Rc::new(headerbar::Header::default());
|
||||||
let ct = content::Content::new(header.clone());
|
let ct = content::Content::new(header.clone());
|
||||||
header.init(ct.clone());
|
header.init(ct.clone());
|
||||||
window.set_titlebar(&header.container);
|
window.set_titlebar(&header.container);
|
||||||
@ -99,11 +91,32 @@ fn build_ui(app: >k::Application) {
|
|||||||
});
|
});
|
||||||
app.add_action(&check);
|
app.add_action(&check);
|
||||||
|
|
||||||
// queue a db update 1 minute after the startup.
|
let update = gio::SimpleAction::new("update", None);
|
||||||
gtk::idle_add(clone!(ct => move || {
|
let ct_clone = ct.clone();
|
||||||
utils::refresh_feed(ct.clone(), None, Some(60));
|
update.connect_activate(move |_, _| {
|
||||||
|
utils::refresh_feed(ct_clone.clone(), None);
|
||||||
|
});
|
||||||
|
app.add_action(&update);
|
||||||
|
|
||||||
|
// Update on startup
|
||||||
|
gtk::timeout_add_seconds(
|
||||||
|
30,
|
||||||
|
clone!(ct => move || {
|
||||||
|
utils::refresh_feed(ct.clone(), None);
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Auto-updater, runs every hour.
|
||||||
|
// TODO: expose the interval in which it run to a user setting.
|
||||||
|
// TODO: show notifications.
|
||||||
|
gtk::timeout_add_seconds(
|
||||||
|
3600,
|
||||||
|
clone!(ct => move || {
|
||||||
|
utils::refresh_feed(ct.clone(), None);
|
||||||
|
glib::Continue(true)
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
gtk::idle_add(move || {
|
gtk::idle_add(move || {
|
||||||
let _ = checkup();
|
let _ = checkup();
|
||||||
|
|||||||
@ -5,14 +5,13 @@ use hammond_data::feed;
|
|||||||
use hammond_data::{Podcast, Source};
|
use hammond_data::{Podcast, Source};
|
||||||
use hammond_downloader::downloader;
|
use hammond_downloader::downloader;
|
||||||
|
|
||||||
use std::{thread, time};
|
use std::thread;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use content::Content;
|
use content::Content;
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
type Foo = RefCell<Option<(Rc<Content>, Receiver<bool>)>>;
|
type Foo = RefCell<Option<(Rc<Content>, Receiver<bool>)>>;
|
||||||
|
|
||||||
// Create a thread local storage that will store the arguments to be transfered.
|
// Create a thread local storage that will store the arguments to be transfered.
|
||||||
@ -22,7 +21,7 @@ thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
|||||||
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
|
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
|
||||||
/// `delay` represents the desired time in seconds for the thread to sleep before executing.
|
/// `delay` represents the desired time in seconds for the thread to sleep before executing.
|
||||||
/// When It's done,it queues up a `podcast_view` refresh.
|
/// When It's done,it queues up a `podcast_view` refresh.
|
||||||
pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>, delay: Option<u64>) {
|
pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>) {
|
||||||
// Create a async channel.
|
// Create a async channel.
|
||||||
let (sender, receiver) = channel();
|
let (sender, receiver) = channel();
|
||||||
|
|
||||||
@ -32,11 +31,6 @@ pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>, delay: Op
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
if let Some(s) = delay {
|
|
||||||
let t = time::Duration::from_secs(s);
|
|
||||||
thread::sleep(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
let feeds = {
|
let feeds = {
|
||||||
if let Some(vec) = source {
|
if let Some(vec) = source {
|
||||||
Ok(feed::fetch(vec))
|
Ok(feed::fetch(vec))
|
||||||
@ -70,6 +64,11 @@ pub fn get_pixbuf_from_path(pd: &Podcast) -> Option<Pixbuf> {
|
|||||||
Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok()
|
Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_pixbuf_from_path_128(pd: &Podcast) -> Option<Pixbuf> {
|
||||||
|
let img_path = downloader::cache_image(pd)?;
|
||||||
|
Pixbuf::new_from_file_at_scale(&img_path, 128, 128, true).ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hammond_data::Source;
|
use hammond_data::Source;
|
||||||
|
|||||||
@ -5,11 +5,17 @@ pub struct EmptyView {
|
|||||||
pub container: gtk::Box,
|
pub container: gtk::Box,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmptyView {
|
impl Default for EmptyView {
|
||||||
pub fn new() -> EmptyView {
|
fn default() -> Self {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui");
|
||||||
let view: gtk::Box = builder.get_object("empty_view").unwrap();
|
let view: gtk::Box = builder.get_object("empty_view").unwrap();
|
||||||
|
|
||||||
EmptyView { container: view }
|
EmptyView { container: view }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EmptyView {
|
||||||
|
pub fn new() -> EmptyView {
|
||||||
|
EmptyView::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -19,18 +19,8 @@ pub struct ShowsPopulated {
|
|||||||
viewport: gtk::Viewport,
|
viewport: gtk::Viewport,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl Default for ShowsPopulated {
|
||||||
struct ShowsChild {
|
fn default() -> Self {
|
||||||
container: gtk::Box,
|
|
||||||
title: gtk::Label,
|
|
||||||
cover: gtk::Image,
|
|
||||||
banner: gtk::Image,
|
|
||||||
number: gtk::Label,
|
|
||||||
child: gtk::FlowBoxChild,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShowsPopulated {
|
|
||||||
pub fn new() -> ShowsPopulated {
|
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_view.ui");
|
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 container: gtk::Box = builder.get_object("fb_parent").unwrap();
|
||||||
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
||||||
@ -42,10 +32,11 @@ impl ShowsPopulated {
|
|||||||
viewport,
|
viewport,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
impl ShowsPopulated {
|
||||||
pub fn new_initialized(show: Rc<ShowStack>, header: Rc<Header>) -> ShowsPopulated {
|
pub fn new(show: Rc<ShowStack>, header: Rc<Header>) -> ShowsPopulated {
|
||||||
let pop = ShowsPopulated::new();
|
let pop = ShowsPopulated::default();
|
||||||
pop.init(show, header);
|
pop.init(show, header);
|
||||||
pop
|
pop
|
||||||
}
|
}
|
||||||
@ -74,7 +65,7 @@ impl ShowsPopulated {
|
|||||||
|
|
||||||
if let Ok(pds) = podcasts {
|
if let Ok(pds) = podcasts {
|
||||||
pds.iter().for_each(|parent| {
|
pds.iter().for_each(|parent| {
|
||||||
let flowbox_child = ShowsChild::new_initialized(parent);
|
let flowbox_child = ShowsChild::new(parent);
|
||||||
self.flowbox.add(&flowbox_child.child);
|
self.flowbox.add(&flowbox_child.child);
|
||||||
});
|
});
|
||||||
self.flowbox.show_all();
|
self.flowbox.show_all();
|
||||||
@ -86,11 +77,20 @@ impl ShowsPopulated {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowsChild {
|
#[derive(Debug)]
|
||||||
fn new() -> ShowsChild {
|
struct ShowsChild {
|
||||||
|
container: gtk::Box,
|
||||||
|
title: gtk::Label,
|
||||||
|
cover: gtk::Image,
|
||||||
|
banner: gtk::Image,
|
||||||
|
number: gtk::Label,
|
||||||
|
child: gtk::FlowBoxChild,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ShowsChild {
|
||||||
|
fn default() -> Self {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_child.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/shows_child.ui");
|
||||||
|
|
||||||
// Copy of gnome-music AlbumWidget
|
|
||||||
let container: gtk::Box = builder.get_object("fb_child").unwrap();
|
let container: gtk::Box = builder.get_object("fb_child").unwrap();
|
||||||
let title: gtk::Label = builder.get_object("pd_title").unwrap();
|
let title: gtk::Label = builder.get_object("pd_title").unwrap();
|
||||||
let cover: gtk::Image = builder.get_object("pd_cover").unwrap();
|
let cover: gtk::Image = builder.get_object("pd_cover").unwrap();
|
||||||
@ -109,6 +109,15 @@ impl ShowsChild {
|
|||||||
child,
|
child,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShowsChild {
|
||||||
|
pub fn new(pd: &Podcast) -> ShowsChild {
|
||||||
|
let child = ShowsChild::default();
|
||||||
|
child.init(pd);
|
||||||
|
|
||||||
|
child
|
||||||
|
}
|
||||||
|
|
||||||
fn init(&self, pd: &Podcast) {
|
fn init(&self, pd: &Podcast) {
|
||||||
self.title.set_text(pd.title());
|
self.title.set_text(pd.title());
|
||||||
@ -122,13 +131,6 @@ impl ShowsChild {
|
|||||||
self.configure_banner(pd);
|
self.configure_banner(pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_initialized(pd: &Podcast) -> ShowsChild {
|
|
||||||
let child = ShowsChild::new();
|
|
||||||
child.init(pd);
|
|
||||||
|
|
||||||
child
|
|
||||||
}
|
|
||||||
|
|
||||||
fn configure_banner(&self, pd: &Podcast) {
|
fn configure_banner(&self, pd: &Podcast) {
|
||||||
let bann =
|
let bann =
|
||||||
Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
|
Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
|
||||||
|
|||||||
@ -47,8 +47,8 @@ struct EpisodeWidget {
|
|||||||
progress_label: gtk::Label,
|
progress_label: gtk::Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpisodeWidget {
|
impl Default for EpisodeWidget {
|
||||||
fn new() -> EpisodeWidget {
|
fn default() -> Self {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
|
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 container: gtk::Box = builder.get_object("episode_container").unwrap();
|
||||||
@ -95,9 +95,11 @@ impl EpisodeWidget {
|
|||||||
progress_label,
|
progress_label,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_initialized(episode: &mut EpisodeWidgetQuery, pd: &Podcast) -> EpisodeWidget {
|
impl EpisodeWidget {
|
||||||
let widget = EpisodeWidget::new();
|
pub fn new(episode: &mut EpisodeWidgetQuery, pd: &Podcast) -> EpisodeWidget {
|
||||||
|
let widget = EpisodeWidget::default();
|
||||||
widget.init(episode, pd);
|
widget.init(episode, pd);
|
||||||
widget
|
widget
|
||||||
}
|
}
|
||||||
@ -109,6 +111,12 @@ impl EpisodeWidget {
|
|||||||
self.title.set_xalign(0.0);
|
self.title.set_xalign(0.0);
|
||||||
self.title.set_text(episode.title());
|
self.title.set_text(episode.title());
|
||||||
|
|
||||||
|
if episode.played().is_some() {
|
||||||
|
self.title
|
||||||
|
.get_style_context()
|
||||||
|
.map(|c| c.add_class("dim-label"));
|
||||||
|
}
|
||||||
|
|
||||||
let progress = self.progress.clone();
|
let progress = self.progress.clone();
|
||||||
timeout_add(200, move || {
|
timeout_add(200, move || {
|
||||||
progress.pulse();
|
progress.pulse();
|
||||||
@ -133,10 +141,16 @@ impl EpisodeWidget {
|
|||||||
self.delete.show();
|
self.delete.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.play.connect_clicked(clone!(episode => move |_| {
|
let title = &self.title;
|
||||||
|
self.play
|
||||||
|
.connect_clicked(clone!(episode, title => move |_| {
|
||||||
let mut episode = episode.clone();
|
let mut episode = episode.clone();
|
||||||
on_play_bttn_clicked(episode.rowid());
|
on_play_bttn_clicked(episode.rowid());
|
||||||
let _ = episode.set_played_now();
|
if episode.set_played_now().is_ok() {
|
||||||
|
title
|
||||||
|
.get_style_context()
|
||||||
|
.map(|c| c.add_class("dim-label"));
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let play = &self.play;
|
let play = &self.play;
|
||||||
@ -234,7 +248,7 @@ fn on_play_bttn_clicked(episode_id: i32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_delete_bttn_clicked(episode_id: i32) {
|
fn on_delete_bttn_clicked(episode_id: i32) {
|
||||||
let mut ep = dbqueries::get_episode_from_id(episode_id).unwrap();
|
let mut ep = dbqueries::get_episode_from_rowid(episode_id).unwrap();
|
||||||
|
|
||||||
let e = delete_local_content(&mut ep);
|
let e = delete_local_content(&mut ep);
|
||||||
if let Err(err) = e {
|
if let Err(err) = e {
|
||||||
@ -269,11 +283,18 @@ fn receive() -> glib::Continue {
|
|||||||
pub fn episodes_listbox(pd: &Podcast) -> Result<gtk::ListBox> {
|
pub fn episodes_listbox(pd: &Podcast) -> Result<gtk::ListBox> {
|
||||||
let episodes = dbqueries::get_pd_episodeswidgets(pd)?;
|
let episodes = dbqueries::get_pd_episodeswidgets(pd)?;
|
||||||
|
|
||||||
// TODO: add a separator
|
|
||||||
let list = gtk::ListBox::new();
|
let list = gtk::ListBox::new();
|
||||||
|
|
||||||
episodes.into_iter().for_each(|mut ep| {
|
episodes.into_iter().for_each(|mut ep| {
|
||||||
let widget = EpisodeWidget::new_initialized(&mut ep, pd);
|
let widget = EpisodeWidget::new(&mut ep, pd);
|
||||||
list.add(&widget.container)
|
list.add(&widget.container);
|
||||||
|
|
||||||
|
let sep = gtk::Separator::new(gtk::Orientation::Vertical);
|
||||||
|
sep.set_sensitive(false);
|
||||||
|
sep.set_can_focus(false);
|
||||||
|
|
||||||
|
list.add(&sep);
|
||||||
|
sep.show()
|
||||||
});
|
});
|
||||||
|
|
||||||
list.set_vexpand(false);
|
list.set_vexpand(false);
|
||||||
|
|||||||
@ -1,57 +1,64 @@
|
|||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk;
|
use gtk;
|
||||||
use diesel::Identifiable;
|
use diesel::Identifiable;
|
||||||
|
use open;
|
||||||
use std::fs;
|
use dissolve;
|
||||||
|
|
||||||
use hammond_data::dbqueries;
|
use hammond_data::dbqueries;
|
||||||
use hammond_data::Podcast;
|
use hammond_data::Podcast;
|
||||||
|
use hammond_data::utils::replace_extra_spaces;
|
||||||
use hammond_downloader::downloader;
|
use hammond_downloader::downloader;
|
||||||
|
|
||||||
use widgets::episode::episodes_listbox;
|
use widgets::episode::episodes_listbox;
|
||||||
use utils::get_pixbuf_from_path;
|
use utils::get_pixbuf_from_path_128;
|
||||||
use content::ShowStack;
|
use content::ShowStack;
|
||||||
use headerbar::Header;
|
use headerbar::Header;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ShowWidget {
|
pub struct ShowWidget {
|
||||||
pub container: gtk::Box,
|
pub container: gtk::Box,
|
||||||
cover: gtk::Image,
|
cover: gtk::Image,
|
||||||
title: gtk::Label,
|
description: gtk::Label,
|
||||||
description: gtk::TextView,
|
link: gtk::Button,
|
||||||
view: gtk::Viewport,
|
settings: gtk::MenuButton,
|
||||||
unsub: gtk::Button,
|
unsub: gtk::Button,
|
||||||
played: gtk::Button,
|
episodes: gtk::Frame,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWidget {
|
impl Default for ShowWidget {
|
||||||
pub fn new() -> ShowWidget {
|
fn default() -> Self {
|
||||||
// Adapted from gnome-music AlbumWidget
|
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/show_widget.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/show_widget.ui");
|
||||||
let container: gtk::Box = builder.get_object("podcast_widget").unwrap();
|
let container: gtk::Box = builder.get_object("container").unwrap();
|
||||||
|
let episodes: gtk::Frame = builder.get_object("episodes").unwrap();
|
||||||
|
|
||||||
let cover: gtk::Image = builder.get_object("cover").unwrap();
|
let cover: gtk::Image = builder.get_object("cover").unwrap();
|
||||||
let title: gtk::Label = builder.get_object("title_label").unwrap();
|
let description: gtk::Label = builder.get_object("description").unwrap();
|
||||||
let description: gtk::TextView = builder.get_object("desc_text_view").unwrap();
|
|
||||||
let view: gtk::Viewport = builder.get_object("view").unwrap();
|
|
||||||
let unsub: gtk::Button = builder.get_object("unsub_button").unwrap();
|
let unsub: gtk::Button = builder.get_object("unsub_button").unwrap();
|
||||||
let played: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
|
let link: gtk::Button = builder.get_object("link_button").unwrap();
|
||||||
|
let settings: gtk::MenuButton = builder.get_object("settings_button").unwrap();
|
||||||
|
|
||||||
|
unsub
|
||||||
|
.get_style_context()
|
||||||
|
.map(|c| c.add_class("destructive-action"));
|
||||||
|
|
||||||
ShowWidget {
|
ShowWidget {
|
||||||
container,
|
container,
|
||||||
cover,
|
cover,
|
||||||
title,
|
|
||||||
description,
|
description,
|
||||||
view,
|
|
||||||
unsub,
|
unsub,
|
||||||
played,
|
link,
|
||||||
|
settings,
|
||||||
|
episodes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_initialized(shows: Rc<ShowStack>, header: Rc<Header>, pd: &Podcast) -> ShowWidget {
|
impl ShowWidget {
|
||||||
let pdw = ShowWidget::new();
|
pub fn new(shows: Rc<ShowStack>, header: Rc<Header>, pd: &Podcast) -> ShowWidget {
|
||||||
|
let pdw = ShowWidget::default();
|
||||||
pdw.init(shows, header, pd);
|
pdw.init(shows, header, pd);
|
||||||
pdw
|
pdw
|
||||||
}
|
}
|
||||||
@ -65,37 +72,29 @@ impl ShowWidget {
|
|||||||
header.switch_to_normal();
|
header.switch_to_normal();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.title.set_text(pd.title());
|
|
||||||
let listbox = episodes_listbox(pd);
|
let listbox = episodes_listbox(pd);
|
||||||
if let Ok(l) = listbox {
|
if let Ok(l) = listbox {
|
||||||
self.view.add(&l);
|
self.episodes.add(&l);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// TODO: Temporary solution until we render html urls/bold/italic probably with markup.
|
||||||
let buff = self.description.get_buffer().unwrap();
|
let desc = dissolve::strip_html_tags(pd.description()).join(" ");
|
||||||
buff.set_text(pd.description());
|
self.description.set_text(&replace_extra_spaces(&desc));
|
||||||
}
|
|
||||||
|
|
||||||
let img = get_pixbuf_from_path(pd);
|
let img = get_pixbuf_from_path_128(pd);
|
||||||
if let Some(i) = img {
|
if let Some(i) = img {
|
||||||
self.cover.set_from_pixbuf(&i);
|
self.cover.set_from_pixbuf(&i);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.played.connect_clicked(clone!(shows, pd => move |_| {
|
let link = pd.link().to_owned();
|
||||||
on_played_button_clicked(shows.clone(), &pd);
|
self.link.connect_clicked(move |_| {
|
||||||
}));
|
info!("Opening link: {}", &link);
|
||||||
|
let _ = open::that(&link);
|
||||||
|
});
|
||||||
|
|
||||||
self.show_played_button(pd);
|
// self.played.connect_clicked(clone!(shows, pd => move |_| {
|
||||||
}
|
// on_played_button_clicked(shows.clone(), &pd);
|
||||||
|
// }));
|
||||||
fn show_played_button(&self, pd: &Podcast) {
|
|
||||||
let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
|
|
||||||
|
|
||||||
if let Ok(n) = new_episodes {
|
|
||||||
if !n.is_empty() {
|
|
||||||
self.played.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +118,7 @@ fn on_unsub_button_clicked(shows: Rc<ShowStack>, pd: &Podcast, unsub_button: >
|
|||||||
shows.update_podcasts();
|
shows.update_podcasts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
fn on_played_button_clicked(shows: Rc<ShowStack>, pd: &Podcast) {
|
fn on_played_button_clicked(shows: Rc<ShowStack>, pd: &Podcast) {
|
||||||
let _ = dbqueries::update_none_to_played_now(pd);
|
let _ = dbqueries::update_none_to_played_now(pd);
|
||||||
|
|
||||||
|
|||||||
19
rustfmt.toml
19
rustfmt.toml
@ -1,26 +1,13 @@
|
|||||||
unstable_features = true
|
unstable_features = true
|
||||||
verbose = false
|
verbose = false
|
||||||
disable_all_formatting = false
|
|
||||||
skip_children = false
|
|
||||||
max_width = 100
|
max_width = 100
|
||||||
comment_width = 100
|
comment_width = 100
|
||||||
wrap_comments = true
|
wrap_comments = true
|
||||||
error_on_line_overflow = true
|
|
||||||
error_on_line_overflow_comments = false
|
|
||||||
tab_spaces = 4
|
tab_spaces = 4
|
||||||
newline_style = "Unix"
|
|
||||||
fn_call_style = "Block"
|
|
||||||
report_todo = "Never"
|
|
||||||
report_fixme = "Never"
|
|
||||||
reorder_extern_crates = true
|
|
||||||
reorder_extern_crates_in_group = true
|
|
||||||
reorder_imports = false
|
|
||||||
hard_tabs = false
|
hard_tabs = false
|
||||||
spaces_within_parens = false
|
newline_style = "Unix"
|
||||||
|
reorder_imports = false
|
||||||
write_mode = "Overwrite"
|
write_mode = "Overwrite"
|
||||||
merge_derives = true
|
|
||||||
condense_wildcard_suffixes = false
|
condense_wildcard_suffixes = false
|
||||||
format_strings = true
|
format_strings = true
|
||||||
multiline_closure_forces_block = true
|
normalize_comments = true
|
||||||
attributes_on_same_line_as_field = true
|
|
||||||
attributes_on_same_line_as_variant = true
|
|
||||||
Loading…
Reference in New Issue
Block a user