Move import

This commit is contained in:
Zander Brown 2018-05-19 21:48:38 +01:00
parent c6ce888cc7
commit ac6ac42860
4 changed files with 93 additions and 79 deletions

View File

@ -326,6 +326,7 @@ Tobias Bernard
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="text" translatable="yes">Import Shows</property>
<property name="action-name">app.import</property>
</object>
<packing>
<property name="expand">False</property>

View File

@ -2,6 +2,20 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<menu id="app-menu">
<section>
<item>
<attribute name="label" translatable="yes">_Check for new episodes</attribute>
<attribute name="action">app.refresh</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Import Shows</attribute>
<attribute name="action">app.import</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Export Shows</attribute>
<attribute name="action">app.export</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>

View File

@ -7,6 +7,7 @@ use gtk::prelude::*;
use gtk::SettingsExt as GtkSettingsExt;
use hammond_data::Podcast;
use hammond_data::{opml};
use appnotif::{InAppNotification, UndoState};
use headerbar::Header;
@ -19,6 +20,8 @@ use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
use rayon;
#[derive(Debug, Clone)]
pub enum Action {
RefreshAllViews,
@ -67,9 +70,21 @@ impl App {
let window = gtk::Window::new(gtk::WindowType::Toplevel);
window.set_title("Hammond");
let (sender, receiver) = channel();
window.connect_delete_event(clone!(application, settings, window => move |_, _| {
WindowGeometry::from_window(&window).write(&settings);
application.quit();
Inhibit(false)
}));
// Ideally a lot more than actions would happen in startup & window
// creation would be in activate
application.connect_startup(clone!(window => move |app| {
application.connect_startup(clone!(window, sender => move |app| {
let import = SimpleAction::new("import", None);
import.connect_activate(clone!(window, sender => move |_, _| on_import_clicked(&window, &sender)));
app.add_action(&import);
let about = SimpleAction::new("about", None);
// Should investigate use of active_window here
about.connect_activate(clone!(window => move |_, _| about_dialog(&window)));
@ -80,14 +95,6 @@ impl App {
app.add_action(&quit);
}));
window.connect_delete_event(clone!(application, settings, window => move |_, _| {
WindowGeometry::from_window(&window).write(&settings);
application.quit();
Inhibit(false)
}));
let (sender, receiver) = channel();
// Create a content instance
let content =
Rc::new(Content::new(sender.clone()).expect("Content Initialization failed."));
@ -274,3 +281,63 @@ fn about_dialog(window: &gtk::Window) {
dialog.show();
}
fn on_import_clicked(window: &gtk::Window, sender: &Sender<Action>) {
use glib::translate::ToGlib;
use gtk::{FileChooserAction, FileChooserDialog, FileFilter, ResponseType};
// let dialog = FileChooserDialog::new(title, Some(&window), FileChooserAction::Open);
// TODO: It might be better to use a FileChooserNative widget.
// Create the FileChooser Dialog
let dialog = FileChooserDialog::with_buttons(
Some("Select the file from which to you want to Import Shows."),
Some(window),
FileChooserAction::Open,
&[
("_Cancel", ResponseType::Cancel),
("_Open", ResponseType::Accept),
],
);
// Do not show hidden(.thing) files
dialog.set_show_hidden(false);
// Set a filter to show only xml files
let filter = FileFilter::new();
FileFilterExt::set_name(&filter, Some("OPML file"));
filter.add_mime_type("application/xml");
filter.add_mime_type("text/xml");
dialog.add_filter(&filter);
dialog.connect_response(clone!(sender => move |dialog, resp| {
debug!("Dialong Response {}", resp);
if resp == ResponseType::Accept.to_glib() {
// TODO: Show an in-app notifictaion if the file can not be accessed
if let Some(filename) = dialog.get_filename() {
debug!("File selected: {:?}", filename);
rayon::spawn(clone!(sender => move || {
// Parse the file and import the feeds
if let Ok(sources) = opml::import_from_file(filename) {
// Refresh the succesfully parsed feeds to index them
utils::refresh(Some(sources), sender)
} else {
let text = String::from("Failed to parse the Imported file");
sender.send(Action::ErrorNotification(text))
.map_err(|err| error!("Action Sender: {}", err))
.ok();
}
}))
} else {
let text = String::from("Selected File could not be accessed.");
sender.send(Action::ErrorNotification(text))
.map_err(|err| error!("Action Sender: {}", err))
.ok();
}
}
dialog.destroy();
}));
dialog.run();
}

View File

@ -4,16 +4,15 @@ use gtk::prelude::*;
use failure::Error;
use failure::ResultExt;
use rayon;
use url::Url;
use hammond_data::{dbqueries, opml, Source};
use hammond_data::{dbqueries, Source};
use std::sync::mpsc::Sender;
use app::Action;
use stacks::Content;
use utils::{self, itunes_to_rss, refresh};
use utils::{itunes_to_rss, refresh};
#[derive(Debug, Clone)]
// TODO: split this into smaller
@ -23,7 +22,6 @@ pub struct Header {
switch: gtk::StackSwitcher,
back: gtk::Button,
show_title: gtk::Label,
import: gtk::ModelButton,
export: gtk::ModelButton,
update_button: gtk::ModelButton,
update_box: gtk::Box,
@ -40,7 +38,6 @@ impl Default for Header {
let switch = builder.get_object("switch").unwrap();
let back = builder.get_object("back").unwrap();
let show_title = builder.get_object("show_title").unwrap();
let import = builder.get_object("import").unwrap();
let export = builder.get_object("export").unwrap();
let update_button = builder.get_object("update_button").unwrap();
let update_box = builder.get_object("update_notification").unwrap();
@ -53,7 +50,6 @@ impl Default for Header {
switch,
back,
show_title,
import,
export,
update_button,
update_box,
@ -104,10 +100,6 @@ impl Header {
}));
}));
self.import.connect_clicked(
clone!(window, sender => move |_| on_import_clicked(&window, &sender)),
);
// Add the Headerbar to the window.
window.set_titlebar(&self.container);
@ -222,63 +214,3 @@ fn on_url_change(
}
}
}
fn on_import_clicked(window: &gtk::Window, sender: &Sender<Action>) {
use glib::translate::ToGlib;
use gtk::{FileChooserAction, FileChooserDialog, FileFilter, ResponseType};
// let dialog = FileChooserDialog::new(title, Some(&window), FileChooserAction::Open);
// TODO: It might be better to use a FileChooserNative widget.
// Create the FileChooser Dialog
let dialog = FileChooserDialog::with_buttons(
Some("Select the file from which to you want to Import Shows."),
Some(window),
FileChooserAction::Open,
&[
("_Cancel", ResponseType::Cancel),
("_Open", ResponseType::Accept),
],
);
// Do not show hidden(.thing) files
dialog.set_show_hidden(false);
// Set a filter to show only xml files
let filter = FileFilter::new();
FileFilterExt::set_name(&filter, Some("OPML file"));
filter.add_mime_type("application/xml");
filter.add_mime_type("text/xml");
dialog.add_filter(&filter);
dialog.connect_response(clone!(sender => move |dialog, resp| {
debug!("Dialong Response {}", resp);
if resp == ResponseType::Accept.to_glib() {
// TODO: Show an in-app notifictaion if the file can not be accessed
if let Some(filename) = dialog.get_filename() {
debug!("File selected: {:?}", filename);
rayon::spawn(clone!(sender => move || {
// Parse the file and import the feeds
if let Ok(sources) = opml::import_from_file(filename) {
// Refresh the succesfully parsed feeds to index them
utils::refresh(Some(sources), sender)
} else {
let text = String::from("Failed to parse the Imported file");
sender.send(Action::ErrorNotification(text))
.map_err(|err| error!("Action Sender: {}", err))
.ok();
}
}))
} else {
let text = String::from("Selected File could not be accessed.");
sender.send(Action::ErrorNotification(text))
.map_err(|err| error!("Action Sender: {}", err))
.ok();
}
}
dialog.destroy();
}));
dialog.run();
}