Commit 1bbe1577 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui

Search Provider: recolor the results using GNOME Shell default theme

parent d04ff7fd
Pipeline #113861 passed with stages
in 6 minutes and 8 seconds
......@@ -317,7 +317,6 @@ dependencies = [
"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)",
......
......@@ -7,10 +7,9 @@ edition = "2018"
[dependencies]
gtk = { version = "0.7", features = ["v3_24"] }
glib = "0.8"
glib-sys = "0.9"
gio = {version = "0.7", features = ["v2_56"] }
gdk = "0.11"
gdk-pixbuf = "0.7"
gdk-pixbuf = {version = "0.7", features = ["v2_32"] }
log = "0.4"
gettext-rs= { version = "0.4", features = ["gettext-system"] }
libhandy = "0.4"
......
use crate::config;
use dbus::arg;
use gtk::prelude::*;
use serde::de;
use serde::Deserialize;
use std::path::{Path, PathBuf};
use std::str::FromStr;
#[derive(Clone, Deserialize)]
pub struct Icon {
......@@ -13,6 +15,52 @@ pub struct Icon {
pub tags: Vec<String>,
}
pub struct IconData {
width: i32,
height: i32,
rowstride: i32,
has_alpha: bool,
bits_per_sample: i32,
n_channels: i32,
data: Vec<u8>,
}
impl IconData {
pub fn new_from_pixbuf(pixbuf: gdk_pixbuf::Pixbuf) -> Option<Self> {
if let Some(bytes) = pixbuf.read_pixel_bytes() {
return Some(Self {
width: pixbuf.get_width(),
height: pixbuf.get_height(),
rowstride: pixbuf.get_rowstride(),
has_alpha: pixbuf.get_has_alpha(),
bits_per_sample: pixbuf.get_bits_per_sample(),
n_channels: pixbuf.get_n_channels(),
data: bytes.to_vec(),
});
}
None
}
}
impl From<IconData> for arg::Variant<Box<dyn arg::RefArg>> {
fn from(icon_data: IconData) -> Self {
/*
From org.gnome.ShellSearchProvider DBus Interface documentation
'icon-data': raw image data as (iiibiiay) - width, height, rowstride,
has-alpha, bits per sample, channels, data
*/
arg::Variant(Box::new((
icon_data.width,
icon_data.height,
icon_data.rowstride,
icon_data.has_alpha,
icon_data.bits_per_sample,
icon_data.n_channels,
icon_data.data.clone(),
)))
}
}
impl Icon {
pub fn should_display(&self, search_str: &String) -> bool {
let icon_name = self.name.to_lowercase();
......@@ -36,6 +84,47 @@ impl Icon {
}
icon_path
}
pub fn get_pixbuf(&self) -> Option<gdk_pixbuf::Pixbuf> {
let theme = gtk::IconTheme::get_default().unwrap();
let icon_info = theme.lookup_icon(&self.name, 24, gtk::IconLookupFlags::FORCE_SYMBOLIC).unwrap();
let is_light = true; // For once we have FreeDesktop dark theme standard
// Default GNOME Shell colors
let mut fg_color = String::new();
let warning_color = String::from("#f57900");
let error_color = String::from("#ff8080");
let mut success_color = String::new();
if is_light {
fg_color.push_str("#eeeeec");
success_color.push_str("#33d17a");
} else {
fg_color.push_str("#2e3436");
success_color.push_str("#229656");
}
if let Ok((pixbuf, _)) = icon_info.load_symbolic(
&gdk::RGBA::from_str(&fg_color).unwrap(), // We are sure that RGBA can parse those colors
Some(&gdk::RGBA::from_str(&success_color).unwrap()),
Some(&gdk::RGBA::from_str(&warning_color).unwrap()),
Some(&gdk::RGBA::from_str(&error_color).unwrap()),
) {
return Some(pixbuf);
}
None
}
pub fn get_icon_data(&self) -> Option<IconData> {
/*
The IconData is used on GNOME Shell Search Provider
The GNOME Shell Search Provider allow sending enough information to recreate a pixbuf
for the images. See gdk_pixbuf_new_from_data
*/
if let Some(pixbuf) = self.get_pixbuf() {
return IconData::new_from_pixbuf(pixbuf);
}
None
}
}
// Until we get https://github.com/serde-rs/serde/issues/368 fixed
......
mod icon;
mod icons;
pub use self::icon::Icon;
pub use self::icon::{Icon, IconData};
pub use self::icons::IconsModel;
......@@ -2,7 +2,6 @@ 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};
......@@ -10,9 +9,6 @@ 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>,
......@@ -65,28 +61,16 @@ impl SearchProvider {
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())));
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))))));
if let Some(icon_data) = icon.get_icon_data() {
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())));
hashmap.insert("icon-data".to_string(), icon_data.into());
let meta = ResultMetadata { hashmap };
metas.insert(0, meta);
let meta = ResultMetadata { hashmap };
metas.insert(0, meta);
}
}
metas
});
......@@ -97,9 +81,10 @@ impl SearchProvider {
let mut sp_ids = Vec::new();
for (_, icons) in icons_by_context {
for icon in icons {
sp_ids.insert(0, icon.name);
sp_ids.push(icon.name);
}
}
sp_ids.sort();
sp_ids
}
}
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