From 158f9eb8991db9c8e6aab21075e53edadc6542f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Cerveau?= Date: Tue, 21 Dec 2021 17:37:17 +0100 Subject: [PATCH] favorites: implement a favorite list The right panel can now store a favorite list which is saved into a settings file in the user config directory. --- Cargo.lock | 390 +++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 + src/app.rs | 137 +++++++++++++-- src/gps.ui | 45 +++-- src/main.rs | 1 + src/plugindialogs.rs | 7 +- src/settings.rs | 86 ++++++++++ 7 files changed, 625 insertions(+), 43 deletions(-) create mode 100644 src/settings.rs diff --git a/Cargo.lock b/Cargo.lock index 876728a..3f39b61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "anyhow" version = "1.0.44" @@ -14,19 +29,56 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cairo-rs" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9164355c892b026d6257e696dde5f3cb39beb3718297f0f161b562fe2ee3ab86" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-sys-rs", "glib", "libc", @@ -44,6 +96,12 @@ dependencies = [ "system-deps 3.2.0", ] +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + [[package]] name = "cfg-expr" version = "0.8.1" @@ -68,12 +126,49 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "error-chain" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" +dependencies = [ + "backtrace", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "field-offset" version = "0.3.4" @@ -167,7 +262,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f97a162c17214d1bf981af3f683156a0b1667dd1927057c4f0a68513251ecf0f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk-pixbuf", "gdk4-sys", @@ -194,13 +289,19 @@ dependencies = [ "system-deps 5.0.0", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "gio" version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711c3632b3ebd095578a9c091418d10fed492da9443f58ebc8f45efbeb215cb0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-io", @@ -230,7 +331,7 @@ version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c515f1e62bf151ef6635f528d05b02c11506de986e43b34a5c920ef0b3796a4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-executor", @@ -308,7 +409,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eff59ca46c4fc5087fd7a0c3770a71ea4b6e94f8c24c12e2c2e8538f9f6fd764" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk4", "glib", @@ -342,10 +443,12 @@ dependencies = [ "glib", "gstreamer", "gtk4", - "log", + "log 0.4.14", "once_cell", + "serde", + "serde_any", "x11", - "xml-rs", + "xml-rs 0.8.4", ] [[package]] @@ -354,7 +457,7 @@ version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6a255f142048ba2c4a4dce39106db1965abe355d23f4b5335edea43a553faa4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "futures-channel", "futures-core", @@ -389,7 +492,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58a04f421d1485ba4739e723199f5828bca05ab4e622ed39a96a342b6b1a6a3d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "field-offset", "futures-channel", @@ -450,6 +553,17 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itertools" version = "0.10.1" @@ -459,12 +573,39 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "libc" version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.14", +] + [[package]] name = "log" version = "0.4.14" @@ -474,6 +615,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + [[package]] name = "memoffset" version = "0.6.4" @@ -483,6 +636,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "muldiv" version = "1.0.0" @@ -519,6 +682,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -531,7 +703,7 @@ version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "546fd59801e5ca735af82839007edd226fe7d3bb06433ec48072be4439c28581" dependencies = [ - "bitflags", + "bitflags 1.3.2", "glib", "libc", "once_cell", @@ -556,6 +728,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + [[package]] name = "pest" version = "2.1.3" @@ -596,7 +774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" dependencies = [ "thiserror", - "toml", + "toml 0.5.8", ] [[package]] @@ -641,6 +819,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ron" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fa11b7a38511d46ff1959ae46ebb60bd8a746f17bdd0206b4c8de7559ac47b" +dependencies = [ + "base64", + "bitflags 1.3.2", + "serde", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustc_version" version = "0.3.3" @@ -650,6 +845,18 @@ dependencies = [ "semver", ] +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "semver" version = "0.11.0" @@ -673,6 +880,83 @@ name = "serde" version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-xml-any" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e281928a3e3104e809dbd19b78cef7ef7c29662cf2583a94c032485aa2e7586b" +dependencies = [ + "error-chain", + "log 0.3.9", + "serde", + "xml-rs 0.6.1", +] + +[[package]] +name = "serde_any" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cb506febacc2cf6533279947bd37b69ce91782af1aedf31c7e6181a77d46ee" +dependencies = [ + "failure", + "ron", + "serde", + "serde-xml-any", + "serde_json", + "serde_urlencoded", + "serde_yaml", + "toml 0.4.10", +] + +[[package]] +name = "serde_derive" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +dependencies = [ + "itoa 1.0.1", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +dependencies = [ + "dtoa", + "itoa 0.4.8", + "serde", + "url", +] + +[[package]] +name = "serde_yaml" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8099d3df28273c99a1728190c7a9f19d444c941044f64adf986bee7ec53051" +dependencies = [ + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", +] [[package]] name = "slab" @@ -715,6 +999,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "system-deps" version = "3.2.0" @@ -729,7 +1025,7 @@ dependencies = [ "strum", "strum_macros", "thiserror", - "toml", + "toml 0.5.8", "version-compare", ] @@ -742,7 +1038,7 @@ dependencies = [ "cfg-expr 0.9.0", "heck", "pkg-config", - "toml", + "toml 0.5.8", "version-compare", ] @@ -766,6 +1062,30 @@ dependencies = [ "syn", ] +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.5.8" @@ -781,6 +1101,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.8.0" @@ -793,6 +1128,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "version-compare" version = "0.0.11" @@ -837,8 +1183,26 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xml-rs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621" +dependencies = [ + "bitflags 0.9.1", +] + [[package]] name = "xml-rs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 393eb22..c4e543e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,5 @@ log = "0.4.11" once_cell = "1.7.2" xml-rs = "0.8.4" x11 = { version = "2.18", features = ["xlib"] } +serde = "1.0" +serde_any = "0.5" \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index c6042c1..8a08e9b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -19,11 +19,12 @@ use glib::Value; use gtk::gdk::Rectangle; use gtk::prelude::*; -use gtk::{gio, glib, graphene}; use gtk::{ - AboutDialog, Application, ApplicationWindow, Builder, Button, FileChooserAction, - FileChooserDialog, PopoverMenu, ResponseType, Statusbar, Viewport, + gdk::BUTTON_SECONDARY, AboutDialog, Application, ApplicationWindow, Builder, Button, + CellRendererText, FileChooserAction, FileChooserDialog, ListStore, PopoverMenu, ResponseType, + Statusbar, TreeView, TreeViewColumn, Viewport, }; +use gtk::{gio, glib, graphene}; use once_cell::unsync::OnceCell; use std::cell::RefCell; use std::collections::HashMap; @@ -32,6 +33,7 @@ use std::{error, ops}; use crate::pipeline::{Pipeline, PipelineState}; use crate::plugindialogs; +use crate::settings::Settings; use crate::graphmanager::{GraphView, Node, PortDirection}; @@ -188,6 +190,109 @@ impl GPSApp { dialog.show(); } + fn reset_favorite_list(&self, favorite_list: &TreeView) { + let model = ListStore::new(&[String::static_type()]); + favorite_list.set_model(Some(&model)); + let favorites = Settings::get_favorites_list(); + for favorite in favorites { + model.insert_with_values(None, &[(0, &favorite)]); + } + } + + fn setup_favorite_list(&self) { + let favorite_list: TreeView = self + .builder + .object("favorites_list") + .expect("Couldn't get window"); + let column = TreeViewColumn::new(); + let cell = CellRendererText::new(); + + column.pack_start(&cell, true); + // Association of the view's column with the model's `id` column. + column.add_attribute(&cell, "text", 0); + column.set_title("favorites"); + favorite_list.append_column(&column); + self.reset_favorite_list(&favorite_list); + let app_weak = self.downgrade(); + favorite_list.connect_row_activated(move |tree_view, _tree_path, _tree_column| { + let app = upgrade_weak!(app_weak); + let selection = tree_view.selection(); + if let Some((model, iter)) = selection.selected() { + let element_name = model + .get(&iter, 0) + .get::() + .expect("Treeview selection, column 1"); + println!("{}", element_name); + app.add_new_element(&element_name); + } + }); + let gesture = gtk::GestureClick::new(); + gesture.set_button(0); + let app_weak = self.downgrade(); + gesture.connect_pressed( + glib::clone!(@weak favorite_list => move |gesture, _n_press, x, y| { + let app = upgrade_weak!(app_weak); + if gesture.current_button() == BUTTON_SECONDARY { + let selection = favorite_list.selection(); + if let Some((model, iter)) = selection.selected() { + let element_name = model + .get(&iter, 0) + .get::() + .expect("Treeview selection, column 1"); + println!("{}", element_name); + let point = graphene::Point::new(x as f32,y as f32); + + + let pop_menu: PopoverMenu = app + .builder + .object("fav_pop_menu") + .expect("Couldn't get menu model for favorites"); + + pop_menu.set_pointing_to(&Rectangle { + x: point.to_vec2().x() as i32, + y: point.to_vec2().y() as i32, + width: 0, + height: 0, + }); + // add an action to delete link + let action = gio::SimpleAction::new("favorite.remove", None); + let app_weak = app.downgrade(); + action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| { + let app = upgrade_weak!(app_weak); + Settings::remove_favorite(&element_name); + app.reset_favorite_list(&favorite_list); + pop_menu.unparent(); + })); + if let Some(application) = app.window.application() { + application.add_action(&action); + } + + pop_menu.show(); + } + + } + }), + ); + favorite_list.add_controller(&gesture); + } + + fn add_to_favorite_list(&self, element_name: String) { + let favorites = Settings::get_favorites_list(); + if !favorites.contains(&element_name) { + let favorite_list: TreeView = self + .builder + .object("favorites_list") + .expect("Couldn't get window"); + if let Some(model) = favorite_list.model() { + let list_store = model + .dynamic_cast::() + .expect("Could not cast to ListStore"); + list_store.insert_with_values(None, &[(0, &element_name)]); + Settings::add_favorite(&element_name); + } + } + } + pub fn build_ui(&self, application: &Application) { let drawing_area_window: Viewport = self .builder @@ -430,6 +535,17 @@ impl GPSApp { width: 0, height: 0, }); + + let action = gio::SimpleAction::new("node.add-to-favorite", None); + let app_weak = app.downgrade(); + action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| { + let app = upgrade_weak!(app_weak); + println!("node.delete {}", node_id); + let node = app.graphview.borrow().node(&node_id).unwrap(); + app.add_to_favorite_list(node.name()); + pop_menu.unparent(); + })); + application.add_action(&action); let action = gio::SimpleAction::new("node.delete", None); let app_weak = app.downgrade(); action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| { @@ -479,6 +595,9 @@ impl GPSApp { }), ) .expect("Failed to register node-right-clicked signal of graphview"); + + // Setup the favorite list + self.setup_favorite_list(); } // Downgrade to a weak reference @@ -489,11 +608,11 @@ impl GPSApp { // Called when the application shuts down. We drop our app struct here fn drop(self) {} - pub fn add_new_element(&self, element_name: String) { + pub fn add_new_element(&self, element_name: &str) { let graph_view = self.graphview.borrow_mut(); let node_id = graph_view.next_node_id(); - let pads = Pipeline::pads(&element_name, false); - if Pipeline::element_is_uri_src_handler(&element_name) { + let pads = Pipeline::pads(element_name, false); + if Pipeline::element_is_uri_src_handler(element_name) { GPSApp::get_file_from_dialog(self, false, move |app, filename| { println!("Open file {}", filename); let node = app.graphview.borrow().node(&node_id).unwrap(); @@ -504,11 +623,7 @@ impl GPSApp { } graph_view.add_node_with_port( node_id, - Node::new( - node_id, - &element_name, - Pipeline::element_type(&element_name), - ), + Node::new(node_id, element_name, Pipeline::element_type(element_name)), pads.0, pads.1, ); diff --git a/src/gps.ui b/src/gps.ui index be1ff34..711a9fa 100644 --- a/src/gps.ui +++ b/src/gps.ui @@ -36,6 +36,14 @@ + +
+ + _Remove favorite + app.favorite.remove + +
+
@@ -60,6 +68,11 @@ app.node.properties <primary>n + + _Add to favorite + app.node.add-to-favorite + <primary>A +
@@ -68,7 +81,11 @@ Stéphane Cerveau True - + + 100 + 1 + 10 + mainwindow 320 @@ -195,12 +212,14 @@ - - - 1 - 1 - - + + + + + True + True + scale_adjustment + 1 @@ -227,12 +246,12 @@ True True - - - - column - - + + + + fav_menu + + diff --git a/src/main.rs b/src/main.rs index 2df081b..45eac1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod common; mod graphmanager; mod pipeline; mod plugindialogs; +mod settings; use gtk::prelude::*; use crate::app::GPSApp; diff --git a/src/plugindialogs.rs b/src/plugindialogs.rs index 6416cc3..034b8d6 100644 --- a/src/plugindialogs.rs +++ b/src/plugindialogs.rs @@ -106,16 +106,11 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) { let app = upgrade_weak!(app_weak); let selection = tree_view.selection(); if let Some((model, iter)) = selection.selected() { - // Now getting back the values from the row corresponding to the - // iterator `iter`. - // - let element_name = model .get(&iter, 1) .get::() .expect("Treeview selection, column 1"); - println!("{}", element_name); - app.add_new_element(element_name); + app.add_new_element(&element_name); } }), ); diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..1da93c9 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,86 @@ +use std::fs::create_dir_all; +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +use crate::common; + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct Settings { + pub favorites: Vec, +} + +impl Settings { + fn settings_file_exist() { + let s = Settings::get_settings_file_path(); + + if !s.exists() { + if let Some(parent_dir) = s.parent() { + if !parent_dir.exists() { + if let Err(e) = create_dir_all(parent_dir) { + println!( + "Error while trying to build settings snapshot_directory '{}': {}", + parent_dir.display(), + e + ); + } + } + } + } + } + + fn get_settings_file_path() -> PathBuf { + let mut path = glib::user_config_dir(); + path.push(common::APPLICATION_NAME); + path.push("settings.toml"); + path + } + + // Public methods + pub fn add_favorite(favorite: &str) { + let mut settings = Settings::load_settings(); + settings.favorites.sort(); + settings.favorites.push(String::from(favorite)); + Settings::save_settings(&settings); + } + + pub fn remove_favorite(favorite: &str) { + let mut settings = Settings::load_settings(); + settings.favorites.retain(|x| x != favorite); + Settings::save_settings(&settings); + } + + pub fn get_favorites_list() -> Vec { + let mut favorites = Vec::new(); + let settings = Settings::load_settings(); + for fav in settings.favorites { + favorites.push(fav); + } + favorites + } + + // Save the provided settings to the settings path + pub fn save_settings(settings: &Settings) { + Settings::settings_file_exist(); + let s = Settings::get_settings_file_path(); + if let Err(e) = serde_any::to_file(&s, settings) { + println!("Error while trying to save file: {} {}", s.display(), e); + } + } + + // Load the current settings + pub fn load_settings() -> Settings { + let s = Settings::get_settings_file_path(); + if s.exists() && s.is_file() { + match serde_any::from_file::(&s) { + Ok(s) => s, + Err(e) => { + println!("Error while opening '{}': {}", s.display(), e); + Settings::default() + } + } + } else { + Settings::default() + } + } +}