Commit 724b2dc9 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui

Add a search provider

This refactors the code a bit to allow having a search provider easily.
parent 11c074c2
Pipeline #108147 passed with stages
in 9 minutes and 37 seconds
......@@ -96,6 +96,15 @@ dependencies = [
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dbus"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)",
"libdbus-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.6.2"
......@@ -302,14 +311,18 @@ dependencies = [
name = "icon-library"
version = "0.0.2"
dependencies = [
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gettext-rs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libhandy 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"search-provider 0.1.0 (git+https://gitlab.gnome.org/bilelmoussaoui/search-provider.git?branch=bilelmoussaoui/update)",
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -330,6 +343,14 @@ name = "libc"
version = "0.2.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libdbus-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libhandy"
version = "0.4.0"
......@@ -499,6 +520,16 @@ name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "search-provider"
version = "0.1.0"
source = "git+https://gitlab.gnome.org/bilelmoussaoui/search-provider.git?branch=bilelmoussaoui/update#e50436d274f96ad775605f9230a9b03337dd7637"
dependencies = [
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.97"
......@@ -623,6 +654,7 @@ dependencies = [
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
"checksum dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "48b5f0f36f1eebe901b0e6bee369a77ed3396334bf3f09abd46454a576f71819"
"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
"checksum fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
"checksum gdk 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6243e995f41f3a61a31847e54cc719edce93dd9140c89dca3b9919be1cfe22d5"
......@@ -642,6 +674,7 @@ dependencies = [
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff"
"checksum libdbus-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69382cb3be797cfe62ba89ac5e594a0e3022914ff44867ffbcfc03daa24eebd7"
"checksum libhandy 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7195919b261667e13240c14004c3fdc1a07a77ee865a9e0da5c2a4e134171c25"
"checksum libhandy-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17019593005fd387b0d2f6e5b29533796e3206e9f433dbf74846a609ceeb5fbf"
"checksum locale_config 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "73ac19ebe45489e5d53b4346d8b90bb3dd03275c5fdf2ce22a982516d86b535c"
......@@ -660,6 +693,7 @@ dependencies = [
"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
"checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum search-provider 0.1.0 (git+https://gitlab.gnome.org/bilelmoussaoui/search-provider.git?branch=bilelmoussaoui/update)" = "<none>"
"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72"
"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
......
......@@ -7,8 +7,10 @@ edition = "2018"
[dependencies]
gtk = { version = "0.7", features = ["v3_24"] }
glib = "0.8"
gio = "0.7"
glib-sys = "0.9"
gio = {version = "0.7", features = ["v2_56"] }
gdk = "0.11"
gdk-pixbuf = "0.7"
log = "0.4"
gettext-rs= { version = "0.4", features = ["gettext-system"] }
libhandy = "0.4"
......@@ -16,4 +18,6 @@ serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
pretty_env_logger = "0.3"
dbus = "0.6"
search-provider = { git = "https://gitlab.gnome.org/bilelmoussaoui/search-provider.git", branch = "bilelmoussaoui/update" }
......@@ -11,7 +11,8 @@
"--share=ipc",
"--socket=x11",
"--socket=wayland",
"--device=dri"
"--device=dri",
"--own-name=org.gnome.design.IconLibrary.SearchProvider"
],
"build-options": {
"append-path": "/usr/lib/sdk/rust-stable/bin",
......
......@@ -19,7 +19,8 @@
"--filesystem=xdg-run/dconf",
"--filesystem=~/.config/dconf:ro",
"--talk-name=ca.desrt.dconf",
"--env=DCONF_USER_CONFIG_DIR=.config/dconf"
"--env=DCONF_USER_CONFIG_DIR=.config/dconf",
"--own-name=org.gnome.design.IconLibraryDevel.SearchProvider"
],
"build-options": {
"append-path": "/usr/lib/sdk/rust-stable/bin",
......
......@@ -109,3 +109,24 @@ install_data(
'resources/icons_dev_kit.json',
install_dir: pkgdatadir
)
# Search Provider
service_conf = configuration_data()
service_conf.set('appid', application_id)
service_conf.set('name', meson.project_name())
service_conf.set('bindir', bindir)
configure_file(
input: 'org.gnome.design.IconLibrary.SearchProvider.service.in',
output: '@0@.SearchProvider.service'.format(application_id),
configuration: service_conf,
install_dir: datadir / 'dbus-1' / 'services'
)
search_conf = configuration_data()
search_conf.set('appid', application_id)
configure_file(
input: 'org.gnome.design.IconLibrary.search-provider.ini',
output: '@0@.search-provider.ini'.format(application_id),
configuration: search_conf,
install_dir: datadir /'gnome-shell' / 'search-providers',
)
[D-BUS Service]
Name=@appid@.SearchProvider
Exec=@bindir@/@name@ --gapplication-service
......@@ -23,6 +23,7 @@
<releases>
<release version="0.0.2" date="2019-08-25">
<description>
<p>Add GNOME Search Provider support.</p>
<p>Translations updates.</p>
</description>
</release>
......@@ -37,6 +38,7 @@
GNOME Software kudos:
https://gitlab.gnome.org/GNOME/gnome-software/blob/master/doc/kudos.md
-->
<kudo>SearchProvider</kudo>
<kudo>ModernToolkit</kudo>
<kudo>HiDpiIcon</kudo>
</kudos>
......
[Shell Search Provider]
DesktopId=@appid@.desktop
BusName=@appid@.SearchProvider
ObjectPath=/org/gnome/design/IconLibrary/SearchProvider
Version=2
......@@ -6,7 +6,7 @@
<object class="GtkStack" id="icons_view">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-left-right</property>
<property name="transition_type">slide-left</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
......
use crate::config;
use crate::icon::Icon;
use crate::widgets::ExportDialog;
use crate::window::Window;
use crate::models::{Icon, IconsModel};
use crate::search_provider::SearchProvider;
use crate::widgets::{ExportDialog, Window};
use gio::prelude::*;
use glib::{Receiver, Sender};
use glib::Receiver;
use gtk::prelude::*;
use std::env;
use std::path::PathBuf;
......@@ -16,7 +16,6 @@ pub enum Action {
pub struct Application {
app: gtk::Application,
window: Window,
sender: Sender<Action>,
receiver: RefCell<Option<Receiver<Action>>>,
}
......@@ -25,13 +24,14 @@ impl Application {
let app = gtk::Application::new(Some(config::APP_ID), Default::default()).unwrap();
let (sender, r) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let receiver = RefCell::new(Some(r));
let window = Window::new(sender.clone());
let model = Rc::new(IconsModel::new());
let window = Window::new(sender.clone(), model.clone());
glib::set_application_name(&format!("{}Icon Library", config::NAME_PREFIX));
glib::set_prgname(Some("icon-library"));
SearchProvider::new(model.clone(), window.widget.clone(), sender.clone());
let application = Self { app, window, sender, receiver };
let application = Self { app, window, receiver };
application.setup_gactions();
application.setup_signals();
......@@ -86,9 +86,13 @@ impl Application {
pub fn setup_signals(&self) {
let window = self.window.widget.clone();
self.app.connect_activate(move |app| {
self.app.connect_startup(move |app| {
window.set_application(Some(app));
app.add_window(&window);
});
let window = self.window.widget.clone();
self.app.connect_activate(move |_| {
window.show_all();
window.present();
});
}
......@@ -97,9 +101,8 @@ impl Application {
match action {
Action::Export(icon) => {
let export_dialog = ExportDialog::new(&icon);
export_dialog.widget.set_transient_for(Some(&self.window.widget));
export_dialog.widget.show_all();
export_dialog.widget.run();
}
}
glib::Continue(true)
......
......@@ -7,9 +7,9 @@ use std::rc::Rc;
mod application;
mod config;
mod icon;
mod models;
mod search_provider;
mod widgets;
mod window;
mod window_state;
use application::Application;
......
......@@ -7,9 +7,9 @@ global_conf.set_quoted('VERSION', version + version_suffix)
global_conf.set_quoted('GETTEXT_PACKAGE', gettext_package)
global_conf.set_quoted('LOCALEDIR', localedir)
config_output_file = configure_file(
input: 'config.rs.in',
output: 'config.rs',
configuration: global_conf
input: 'config.rs.in',
output: 'config.rs',
configuration: global_conf
)
# Copy the config.rs output to the source directory.
run_command(
......@@ -20,15 +20,18 @@ run_command(
)
sources = files(
'widgets/icons.rs',
'widgets/export.rs',
'widgets/mod.rs',
'application.rs',
'config.rs',
'icon.rs',
'main.rs',
'window.rs',
'window_state.rs',
'models/icon.rs',
'models/icons.rs',
'models/mod.rs',
'widgets/icons.rs',
'widgets/export.rs',
'widgets/mod.rs',
'widgets/window.rs',
'application.rs',
'config.rs',
'main.rs',
'search_provider.rs',
'window_state.rs',
)
cargo_release = custom_target(
......
use crate::config;
use gtk::prelude::*;
use serde::de;
use serde::Deserialize;
use std::path::{Path, PathBuf};
#[derive(Clone, Deserialize)]
pub struct Icon {
......@@ -12,11 +15,26 @@ pub struct Icon {
impl Icon {
pub fn should_display(&self, search_str: &String) -> bool {
let icon_name = self.name.to_lowercase();
let icon_terms: Vec<&str> = icon_name.split("-").collect();
let search_str = search_str.to_lowercase();
// Check if the icon should be shown for the searched string
let mut found_tags = self.tags.clone();
found_tags.retain(|tag| tag.to_lowercase().contains(search_str.as_str()));
self.name.to_lowercase().contains(search_str.as_str()) || found_tags.len() != 0
icon_terms.contains(&search_str.as_str()) || found_tags.len() != 0
}
pub fn get_path(&self) -> PathBuf {
let mut icon_path = Path::new("").to_path_buf();
if self.is_system {
let theme = gtk::IconTheme::get_default().unwrap();
let icon_info = theme.lookup_icon(&self.name, -1, gtk::IconLookupFlags::FORCE_SYMBOLIC).unwrap();
icon_path.push(icon_info.get_filename().unwrap());
} else {
let icon_uri: PathBuf = [config::PKGDATADIR, "icon-dev-kit", &format!("{}.svg", self.name)].iter().collect();
icon_path.push(icon_uri);
}
icon_path
}
}
......
use super::icon::Icon;
use crate::config;
use gettextrs::gettext;
use gtk::prelude::*;
use std::cell::RefCell;
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
pub struct IconsModel {
data: RefCell<Vec<(String, Vec<Icon>)>>,
}
impl IconsModel {
pub fn new() -> Self {
let data: RefCell<Vec<(String, Vec<Icon>)>> = RefCell::new(Vec::new());
let model = Self { data };
model.init();
model
}
pub fn get_icon_byname(&self, icon_name: String) -> Icon {
let icons = self.data.borrow().clone();
let found_icons: Vec<Icon> = icons
.into_iter()
.map(|(_, icons)| -> Vec<Icon> {
icons
.into_iter()
.filter(|icon| {
// filter out unneeded icons
icon.name == icon_name
})
.collect()
})
.flatten()
.collect();
found_icons.get(0).unwrap().clone()
}
pub fn get_icons(&self) -> Vec<(String, Vec<Icon>)> {
self.data.borrow().clone()
}
pub fn filter(&self, terms: Vec<&str>) -> Vec<(String, Vec<Icon>)> {
let icons = self.data.borrow().clone();
icons
.into_iter()
.map(|(context, icons)| -> (String, Vec<Icon>) {
let found_icons = icons
.into_iter()
.filter(|icon| {
// filter out unneeded icons
terms.iter().filter(|k| icon.should_display(&k.to_string())).collect::<Vec<&&str>>().len() != 0
})
.collect();
(context, found_icons)
})
.filter(|(_, found_icons): &(String, Vec<Icon>)| found_icons.len() != 0)
.collect()
}
fn init(&self) {
let dev_kit_file: PathBuf = [config::PKGDATADIR, "icons_dev_kit.json"].iter().collect();
let file = File::open(dev_kit_file).expect("Failed to open icons_dev_kit.json");
let reader = BufReader::new(file);
let mut dev_kit_icons: Vec<Icon> = serde_json::from_reader(reader).expect("Failed to parse json file");
dev_kit_icons.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
self.add_context(gettext("General").to_string(), dev_kit_icons);
// Load default theme icons
let theme = gtk::IconTheme::get_default().unwrap();
let mut icon_contexts = theme.list_contexts();
icon_contexts.sort_by(|a, b| a.as_str().cmp(&b.as_str()));
let legacy_contexts = vec!["Legacy"];
let app_icon = format!("{}-symbolic", config::APP_ID);
let icons_blacklist = vec![
"gesture-rotate-clockwise-symbolic",
"gesture-pinch-symbolic",
"gesture-two-finger-swipe-left-symbolic",
"gesture-two-finger-swipe-right-symbolic",
"gesture-stretch-symbolic",
"gesture-rotate-anticlockwise-symbolic",
app_icon.as_str(),
];
for context in icon_contexts.iter() {
let context_str = context.as_str();
if legacy_contexts.contains(&context_str) {
continue;
}
let mut icons: Vec<Icon> = theme
.list_icons(Some(context_str))
.into_iter()
.filter(|icon_name| {
// filter out unneeded icons
!icons_blacklist.contains(&icon_name.as_str()) && icon_name.ends_with("-symbolic")
})
.map(|icon_name| Icon {
name: icon_name.as_str().to_string(),
is_system: true,
tags: [context_str.to_string()].to_vec(),
})
.collect();
icons.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
self.add_context(context_str.to_string(), icons);
}
}
fn add_context(&self, context: String, icons: Vec<Icon>) {
self.data.borrow_mut().push((context, icons));
}
}
mod icon;
mod icons;
pub use self::icon::Icon;
pub use self::icons::IconsModel;
use crate::application::Action;
use crate::config::APP_ID;
use crate::models::IconsModel;
use dbus::arg;
use gio::prelude::*;
use glib::Sender;
use gtk::prelude::*;
use search_provider::{ResultMetadata, SearchProvider as SP};
use std::collections::HashMap;
use std::sync::Arc;
use std::{cell::RefCell, rc::Rc};
use glib::translate::*;
use glib_sys;
#[derive(Clone)]
pub struct SearchProvider {
search_provider: Arc<SP>,
window: gtk::ApplicationWindow,
sender: Sender<Action>,
model: Rc<IconsModel>,
}
impl SearchProvider {
pub fn new(model: Rc<IconsModel>, window: gtk::ApplicationWindow, sender: Sender<Action>) -> Rc<RefCell<Self>> {
let search_provider = SP::new(APP_ID.to_string(), "/org/gnome/design/IconLibrary/SearchProvider".to_string());
let sp = Rc::new(RefCell::new(Self {
search_provider,
window,
model,
sender,
}));
sp.borrow().setup_callbacks(sp.clone());
sp
}
fn setup_callbacks(&self, s: Rc<RefCell<Self>>) {
let window = self.window.clone();
let sender = self.sender.clone();
let sp = s.clone();
self.search_provider.connect_activate_result(move |sp_id, _, timestamp| {
// Show window
window.present_with_time(timestamp);
window.show_all();
window.present();
// Get the Icon
let icon = sp.borrow().model.get_icon_byname(sp_id.to_string());
// Display the Export window
sender.send(Action::Export(icon)).expect("Action channel blew up somehow");
});
let sp = s.clone();
self.search_provider.connect_get_initial_result_set(move |terms| sp.borrow().clone().search(terms));
let sp = s.clone();
self.search_provider.connect_get_subsearch_result_set(move |_, terms| sp.borrow().clone().search(terms));
let sp = s.clone();
self.search_provider.connect_get_result_metas(move |sp_ids| {
let mut metas = Vec::new();
for sp_id in sp_ids {
let icon_name = sp_id.clone();
let icon = sp.borrow().model.get_icon_byname(icon_name.to_string());
let icon_path = icon.get_path();
let mut hashmap: HashMap<String, arg::Variant<Box<arg::RefArg + 'static>>> = HashMap::new();
hashmap.insert("id".to_string(), arg::Variant(Box::new(sp_id.to_string())));
hashmap.insert("name".to_string(), arg::Variant(Box::new(icon_name.to_string())));
hashmap.insert("description".to_string(), arg::Variant(Box::new("".to_string())));
if !icon.is_system {
let gfile = gio::File::new_for_path(icon_path);
let (gbytes, _) = gfile.load_bytes(gio::NONE_CANCELLABLE).expect("Failed to read icon bytes");
let gicon = gio::BytesIcon::new(&gbytes);
let variant = gicon.serialize().unwrap();
let gbytes = unsafe {
let bytes_variant = glib_sys::g_variant_get_child_value(variant.to_glib_none().0, 1);
let bytes: glib::Bytes = from_glib_full(glib_sys::g_variant_get_data_as_bytes(bytes_variant));
bytes
};
let bytes: Vec<u8> = gbytes.to_vec();
hashmap.insert("icon".to_string(), arg::Variant(Box::new(("bytes".to_string(), arg::Variant(Box::new(bytes))))));
  • My rust foo is very much non-existent, so I may very well talk rubbish here: Are you reimplementing GIcon serialization here? icon is expected to be a serialized GIcon, so I would expect something like gicon.serialize() here ...

  • Yes he is, I believe the problem is that serialize() provides a GVariant whereas the dbus create (library) used has it's own variant type

Please register or sign in to reply
} else {
hashmap.insert("icon".to_string(), arg::Variant(Box::new(icon_name.to_string())));
}
let meta = ResultMetadata { hashmap };
metas.insert(0, meta);
}
metas
});
}
fn search(self, terms: Vec<&str>) -> Vec<String> {
let icons_by_context = self.model.filter(terms);
let mut sp_ids = Vec::new();
for (_, icons) in icons_by_context {
for icon in icons {
sp_ids.insert(0, icon.name);
}
}
sp_ids
}
}
use crate::icon::Icon;
use crate::models::Icon;
use gettextrs::gettext;
use gio::prelude::*;
use gtk::prelude::*;
......@@ -126,11 +126,15 @@ impl ExportDialog {
actions.add_action(&copy_icon);
// Quit
self.widget.connect_delete_event(|w, _| {
w.destroy();
gtk::Inhibit(false)
});
self.widget.connect_key_press_event(|w, k| {
if k.get_keyval() == gdk::enums::key::Escape {
w.close();
w.destroy();
}
Inhibit(true)
gtk::Inhibit(false)
});
}
}
use crate::application::Action;
use crate::config;
use crate::icon::Icon;
use gettextrs::gettext;
use crate::models::Icon;
use gtk::prelude::*;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
pub struct IconsView {
pub widget: gtk::Stack,
builder: gtk::Builder,
icons_contexts: Vec<RefCell<IconsViewContext>>,
sender: glib::Sender<Action>,
}
......@@ -23,65 +19,14 @@ impl IconsView {
let icons_contexts: Vec<RefCell<IconsViewContext>> = Vec::new();
let mut icons_view = IconsView {
let icons_view = IconsView {
widget,
builder,
icons_contexts,
sender,
};
icons_view.fill();