Commit 4d3393a8 authored by Felix Häcker's avatar Felix Häcker

Rewrite StationObject to ObjectWrapper to make it generic. Now we can use it...

Rewrite StationObject to ObjectWrapper to make it generic. Now we can use it for other structs (like Song) too. Move model stuff into new module folder
parent f124f86f
Pipeline #68509 passed with stages
in 8 minutes and 7 seconds
......@@ -1346,7 +1346,7 @@ dependencies = [
"hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1374,7 +1374,7 @@ dependencies = [
"openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"protoc-rust 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -1404,7 +1404,7 @@ source = "git+https://gitlab.gnome.org/haecker-felix/Rustio.git#093874769bf486e3
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"restson 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -1468,7 +1468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.88"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
......@@ -1488,7 +1488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -1513,6 +1513,7 @@ dependencies = [
"rusqlite 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rust_cast 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustio 0.0.1 (git+https://gitlab.gnome.org/haecker-felix/Rustio.git)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"stopwatch 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -2070,7 +2071,7 @@ dependencies = [
"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560"
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
......
......@@ -25,5 +25,6 @@ uuid = { version = "0.7", features = ["v4"] }
chrono = "0.4.6"
rust_cast = "0.14.0"
mdns = "0.3.1"
serde = "1.0.89"
serde_json = "1.0.39"
lazy_static = "1.3.0"
......@@ -8,9 +8,9 @@ use std::rc::Rc;
use crate::config;
use crate::library::Library;
use crate::model::{Order, Sorting};
use crate::player::{PlaybackState, Player};
use crate::search::Search;
use crate::station_model::{Order, Sorting};
use crate::window::{View, Window};
#[derive(Debug, Clone)]
......@@ -246,8 +246,7 @@ impl App {
Ok(stations) => {
let message = format!("Successfully imported {} stations.", stations.len());
self.sender.send(Action::ViewShowNotification(message)).unwrap();
self.sender.send(Action::LibraryAddStations(stations));
self.sender.send(Action::LibraryAddStations(stations)).unwrap();
}
Err(error) => {
let message = format!("Could not import stations: {}", error.to_string());
......
......@@ -6,17 +6,15 @@ use rustio::{Client, Station};
use std::cell::RefCell;
use std::fs;
use std::fs::File;
use std::io;
use std::path::PathBuf;
use std::result::Result;
use std::thread;
use crate::app::Action;
use crate::config;
use crate::station_model::StationModel;
use crate::station_model::{Order, Sorting};
use crate::station_object::StationObject;
use crate::model::ObjectWrapper;
use crate::model::StationModel;
use crate::model::{Order, Sorting};
use crate::widgets::station_listbox::StationListBox;
lazy_static! {
......@@ -32,7 +30,6 @@ pub struct Library {
pub widget: gtk::Box,
library_model: RefCell<StationModel>,
builder: gtk::Builder,
sender: Sender<Action>,
}
......@@ -52,12 +49,7 @@ impl Library {
let welcome_text: gtk::Label = builder.get_object("welcome_text").unwrap();
welcome_text.set_text(format!("Welcome to {}", config::NAME).as_str());
let library = Self {
widget,
library_model,
builder,
sender,
};
let library = Self { widget, library_model, sender };
library.setup_signals();
......@@ -99,15 +91,15 @@ impl Library {
let mut stations = Vec::new();
for i in 0..model.get_n_items() {
let gobject = model.get_object(i).unwrap();
let station_object = gobject.downcast_ref::<StationObject>().expect("StationObject is of wrong type");
stations.insert(0, station_object.to_station());
let station_object = gobject.downcast_ref::<ObjectWrapper>().expect("ObjectWrapper is of wrong type");
stations.insert(0, station_object.deserialize());
}
stations
}
fn setup_signals(&self) {
let sender = self.sender.clone();
self.library_model.borrow().model.connect_items_changed(move |model, pos, removed, added| {
self.library_model.borrow().model.connect_items_changed(move |model, _, removed, added| {
// Check if data got changed
if removed == 1 || added == 1 {
// Convert gio::ListStore into Vec<Station>
......
......@@ -11,16 +11,16 @@ extern crate glib;
#[macro_use]
extern crate lazy_static;
mod model;
mod player;
mod widgets;
mod app;
mod config;
mod library;
mod player;
mod search;
mod song;
mod static_resource;
mod station_model;
mod station_object;
mod widgets;
mod window;
use crate::app::App;
......
mod object_wrapper;
mod station_model;
//mod song_model;
pub use object_wrapper::ObjectWrapper;
pub use station_model::Order;
pub use station_model::Sorting;
pub use station_model::StationModel;
// StationObject is a GObject subclass, which we need to carry the rustio::Station struct.
// ObjectWrapper is a GObject subclass, which we need to carry the rustio::Station/song::Song struct.
// With this we can use gtk::ListBox bind_model() properly.
//
// For more details, you should look at this gtk-rs example:
// https://github.com/gtk-rs/examples/blob/master/src/bin/listbox_model.rs
use super::*;
use gtk::prelude::*;
use rustio::Station;
use serde::de::DeserializeOwned;
use glib::subclass;
use glib::subclass::prelude::*;
......@@ -16,7 +15,7 @@ mod imp {
use super::*;
use std::cell::RefCell;
pub struct StationObject {
pub struct ObjectWrapper {
data: RefCell<Option<String>>,
}
......@@ -30,8 +29,8 @@ mod imp {
)
})];
impl ObjectSubclass for StationObject {
const NAME: &'static str = "StationObject";
impl ObjectSubclass for ObjectWrapper {
const NAME: &'static str = "ObjectWrapper";
type ParentType = glib::Object;
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
......@@ -47,7 +46,7 @@ mod imp {
}
}
impl ObjectImpl for StationObject {
impl ObjectImpl for ObjectWrapper {
glib_object_impl!();
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
......@@ -74,22 +73,28 @@ mod imp {
}
glib_wrapper! {
pub struct StationObject(Object<subclass::simple::InstanceStruct<imp::StationObject>, subclass::simple::ClassStruct<imp::StationObject>, StationObjectClass>);
pub struct ObjectWrapper(Object<subclass::simple::InstanceStruct<imp::ObjectWrapper>, subclass::simple::ClassStruct<imp::ObjectWrapper>, ObjectWrapperClass>);
match fn {
get_type => || imp::StationObject::get_type().to_glib(),
get_type => || imp::ObjectWrapper::get_type().to_glib(),
}
}
impl StationObject {
pub fn new(station: Station) -> StationObject {
glib::Object::new(Self::static_type(), &[("data", &serde_json::to_string(&station).unwrap())])
impl ObjectWrapper {
pub fn new<O>(object: O) -> ObjectWrapper
where
O: serde::ser::Serialize,
{
glib::Object::new(Self::static_type(), &[("data", &serde_json::to_string(&object).unwrap())])
.unwrap()
.downcast()
.unwrap()
}
pub fn to_station(&self) -> Station {
pub fn deserialize<O>(&self) -> O
where
O: DeserializeOwned,
{
let data = self.get_property("data").unwrap().get::<String>().unwrap();
serde_json::from_str(&data).unwrap()
}
......
use gio::prelude::ListStoreExtManual;
use gio::prelude::*;
use glib::prelude::*;
use crate::song::Song;
use crate::song_object::SongObject;
#[derive(Clone, Debug)]
pub struct SongModel {
pub model: gio::ListStore,
}
impl SongModel {
pub fn new() -> Self {
let model = gio::ListStore::new(SongObject::static_type());
Self { model, sorting, order }
}
pub fn add_song(&mut self, song: Song) {
if !self.index(&song).is_some() {
let object = SongObject::new(song.clone());
let sorting = self.sorting.clone();
let order = self.order.clone();
self.model.insert(&object);
}
}
pub fn remove_song(&mut self, song: &Song) {
self.index(song).map(|index| self.model.remove(index));
}
fn index(&self, song: &Song) -> Option<u32> {
for i in 0..self.model.get_n_items() {
let gobject = self.model.get_object(i).unwrap();
let song_object = gobject.downcast_ref::<SongObject>().expect("SongObject is of wrong type");
let s = song_object.to_song();
if &s == song {
return Some(i);
}
}
None
}
pub fn clear(&mut self) {
self.model.remove_all();
}
}
......@@ -3,7 +3,7 @@ use gio::prelude::*;
use glib::prelude::*;
use rustio::Station;
use crate::station_object::StationObject;
use crate::model::ObjectWrapper;
#[derive(Clone, Debug)]
pub enum Sorting {
......@@ -27,25 +27,21 @@ pub struct StationModel {
pub model: gio::ListStore,
sorting: Sorting,
order: Order,
iter_id: u32,
}
impl StationModel {
pub fn new() -> Self {
let model = gio::ListStore::new(StationObject::static_type());
let model = gio::ListStore::new(ObjectWrapper::static_type());
let sorting = Sorting::Name;
let order = Order::Ascending;
let iter_id = 0;
Self { model, sorting, order, iter_id }
Self { model, sorting, order }
}
pub fn add_station(&mut self, station: Station) {
if !self.index(&station).is_some() {
let object = StationObject::new(station.clone());
let object = ObjectWrapper::new(station.clone());
let sorting = self.sorting.clone();
let order = self.order.clone();
self.model.insert_sorted(&object, move |a, b| Self::station_cmp(a, b, sorting.clone(), order.clone()));
......@@ -59,8 +55,8 @@ impl StationModel {
fn index(&self, station: &Station) -> Option<u32> {
for i in 0..self.model.get_n_items() {
let gobject = self.model.get_object(i).unwrap();
let station_object = gobject.downcast_ref::<StationObject>().expect("StationObject is of wrong type");
let s = station_object.to_station();
let station_object = gobject.downcast_ref::<ObjectWrapper>().expect("ObjectWrapper is of wrong type");
let s: Station = station_object.deserialize();
if &s == station {
return Some(i);
......@@ -80,13 +76,9 @@ impl StationModel {
self.model.remove_all();
}
pub fn len(&self) -> u32 {
self.model.get_n_items()
}
fn station_cmp(a: &gio::Object, b: &gio::Object, sorting: Sorting, order: Order) -> std::cmp::Ordering {
let mut station_a: Station = a.downcast_ref::<StationObject>().unwrap().to_station();
let mut station_b: Station = b.downcast_ref::<StationObject>().unwrap().to_station();
let mut station_a: Station = a.downcast_ref::<ObjectWrapper>().unwrap().deserialize();
let mut station_b: Station = b.downcast_ref::<ObjectWrapper>().unwrap().deserialize();
if order == Order::Descending {
let tmp = station_a;
......
......@@ -5,7 +5,7 @@ use rustio::{Client, StationSearch};
use std::cell::RefCell;
use crate::app::Action;
use crate::station_model::StationModel;
use crate::model::StationModel;
use crate::widgets::station_listbox::StationListBox;
pub struct Search {
......
......@@ -90,7 +90,7 @@ impl StationDialog {
let remove_button: gtk::Button = self.builder.get_object("remove_button").unwrap();
let sender = self.sender.clone();
let station = self.station.clone();
remove_button.connect_clicked(move |btn| {
remove_button.connect_clicked(move |_| {
sender.send(Action::LibraryRemoveStations(vec![station.clone()])).unwrap();
library_action_stack.set_visible_child_name("library-add");
});
......@@ -100,7 +100,7 @@ impl StationDialog {
let add_button: gtk::Button = self.builder.get_object("add_button").unwrap();
let sender = self.sender.clone();
let station = self.station.clone();
add_button.connect_clicked(move |btn| {
add_button.connect_clicked(move |_| {
sender.send(Action::LibraryAddStations(vec![station.clone()])).unwrap();
library_action_stack.set_visible_child_name("library-remove");
});
......
......@@ -3,8 +3,8 @@ use gtk::prelude::*;
use libhandy::{Column, ColumnExt};
use crate::app::Action;
use crate::station_model::StationModel;
use crate::station_object::StationObject;
use crate::model::ObjectWrapper;
use crate::model::StationModel;
use crate::widgets::station_row::StationRow;
pub struct StationListBox {
......@@ -36,7 +36,7 @@ impl StationListBox {
let sender = self.sender.clone();
self.listbox.bind_model(&model.model, move |station| {
let row = StationRow::new(sender.clone(), station.downcast_ref::<StationObject>().unwrap().to_station());
let row = StationRow::new(sender.clone(), station.downcast_ref::<ObjectWrapper>().unwrap().deserialize());
row.widget.upcast::<gtk::Widget>()
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment