Merge branch 'translation' into 'master'
Use xkb layout names from gnome See merge request Librem5/squeekboard!280
This commit is contained in:
		
							
								
								
									
										1
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@ -9,6 +9,7 @@ Build-Depends:
 | 
				
			|||||||
 ninja-build,
 | 
					 ninja-build,
 | 
				
			||||||
 pkg-config,
 | 
					 pkg-config,
 | 
				
			||||||
 libglib2.0-dev,
 | 
					 libglib2.0-dev,
 | 
				
			||||||
 | 
					 libgnome-desktop-3-dev,
 | 
				
			||||||
 libgtk-3-dev,
 | 
					 libgtk-3-dev,
 | 
				
			||||||
 libcroco3-dev,
 | 
					 libcroco3-dev,
 | 
				
			||||||
 librust-bitflags-1-dev (>= 1.0),
 | 
					 librust-bitflags-1-dev (>= 1.0),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,24 +1,99 @@
 | 
				
			|||||||
/*! Locale-specific functions */
 | 
					/*! Locale-specific functions. 
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This file is intended as a library:
 | 
				
			||||||
 | 
					 * it must pass errors upwards
 | 
				
			||||||
 | 
					 * and panicking is allowed only when
 | 
				
			||||||
 | 
					 * this code encounters an internal inconsistency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::cmp;
 | 
					use std::cmp;
 | 
				
			||||||
use std::ffi::CString;
 | 
					use std::ffi::{ CStr, CString };
 | 
				
			||||||
 | 
					use std::os::raw::c_char;
 | 
				
			||||||
 | 
					use std::ptr;
 | 
				
			||||||
 | 
					use std::str::Utf8Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod c {
 | 
					mod c {
 | 
				
			||||||
    use std::os::raw::c_char;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					    use std::os::raw::c_void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[allow(non_camel_case_types)]
 | 
					    #[allow(non_camel_case_types)]
 | 
				
			||||||
    pub type c_int = i32;
 | 
					    pub type c_int = i32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[derive(Clone, Copy)]
 | 
				
			||||||
 | 
					    #[repr(C)]
 | 
				
			||||||
 | 
					    pub struct GnomeXkbInfo(*const c_void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    extern "C" {
 | 
					    extern "C" {
 | 
				
			||||||
        // from libc
 | 
					        // from libc
 | 
				
			||||||
        pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
 | 
					        pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
 | 
				
			||||||
 | 
					        // from gnome-desktop3
 | 
				
			||||||
 | 
					        pub fn gnome_xkb_info_new() -> GnomeXkbInfo;
 | 
				
			||||||
 | 
					        pub fn gnome_xkb_info_get_layout_info (
 | 
				
			||||||
 | 
					            info: GnomeXkbInfo,
 | 
				
			||||||
 | 
					            id: *const c_char,
 | 
				
			||||||
 | 
					            display_name: *mut *const c_char,
 | 
				
			||||||
 | 
					            short_name: *const *const c_char,
 | 
				
			||||||
 | 
					            xkb_layout: *const *const c_char,
 | 
				
			||||||
 | 
					            xkb_variant: *const *const c_char
 | 
				
			||||||
 | 
					        ) -> c_int;
 | 
				
			||||||
 | 
					        pub fn g_object_unref(o: GnomeXkbInfo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub enum Error {
 | 
				
			||||||
 | 
					    StringConversion(Utf8Error),
 | 
				
			||||||
 | 
					    NoInfo,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct XkbInfo(c::GnomeXkbInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl XkbInfo {
 | 
				
			||||||
 | 
					    pub fn new() -> XkbInfo {
 | 
				
			||||||
 | 
					        XkbInfo(unsafe { c::gnome_xkb_info_new() })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn get_display_name(&self, id: &str) -> Result<String, Error> {
 | 
				
			||||||
 | 
					        let id = cstring_safe(id);
 | 
				
			||||||
 | 
					        let id_ref = id.as_ptr();
 | 
				
			||||||
 | 
					        let mut display_name: *const c_char = ptr::null();
 | 
				
			||||||
 | 
					        let found = unsafe {
 | 
				
			||||||
 | 
					            c::gnome_xkb_info_get_layout_info(
 | 
				
			||||||
 | 
					                self.0,
 | 
				
			||||||
 | 
					                id_ref,
 | 
				
			||||||
 | 
					                &mut display_name as *mut *const c_char,
 | 
				
			||||||
 | 
					                ptr::null(), ptr::null(), ptr::null(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        if found != 0 && !display_name.is_null() {
 | 
				
			||||||
 | 
					            let display_name = unsafe { CStr::from_ptr(display_name) };
 | 
				
			||||||
 | 
					            display_name.to_str()
 | 
				
			||||||
 | 
					                .map(str::to_string)
 | 
				
			||||||
 | 
					                .map_err(Error::StringConversion)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(Error::NoInfo)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Drop for XkbInfo {
 | 
				
			||||||
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
 | 
					        unsafe { c::g_object_unref(self.0) }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Debug, PartialEq)]
 | 
					#[derive(Clone, Debug, PartialEq)]
 | 
				
			||||||
pub struct Translation<'a>(pub &'a str);
 | 
					pub struct Translation<'a>(pub &'a str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Translation<'a> {
 | 
				
			||||||
 | 
					    pub fn to_owned(&'a self) -> OwnedTranslation {
 | 
				
			||||||
 | 
					        OwnedTranslation(self.0.to_owned())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq)]
 | 
				
			||||||
 | 
					pub struct OwnedTranslation(pub String);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn cstring_safe(s: &str) -> CString {
 | 
					fn cstring_safe(s: &str) -> CString {
 | 
				
			||||||
    CString::new(s)
 | 
					    CString::new(s)
 | 
				
			||||||
        .unwrap_or(CString::new("").unwrap())
 | 
					        .unwrap_or(CString::new("").unwrap())
 | 
				
			||||||
 | 
				
			|||||||
@ -70,12 +70,12 @@ pub enum Level {
 | 
				
			|||||||
/// Approach 2.
 | 
					/// Approach 2.
 | 
				
			||||||
pub trait Warn {
 | 
					pub trait Warn {
 | 
				
			||||||
    type Value;
 | 
					    type Value;
 | 
				
			||||||
    fn ok_warn(self, msg: &str) -> Option<Self::Value>;
 | 
					    fn or_warn(self, msg: &str) -> Option<Self::Value>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T, E: Error> Warn for Result<T, E> {
 | 
					impl<T, E: Error> Warn for Result<T, E> {
 | 
				
			||||||
    type Value = T;
 | 
					    type Value = T;
 | 
				
			||||||
    fn ok_warn(self, msg: &str) -> Option<T> {
 | 
					    fn or_warn(self, msg: &str) -> Option<T> {
 | 
				
			||||||
        self.map_err(|e| {
 | 
					        self.map_err(|e| {
 | 
				
			||||||
            eprintln!("{}: {}", msg, e);
 | 
					            eprintln!("{}: {}", msg, e);
 | 
				
			||||||
            e
 | 
					            e
 | 
				
			||||||
@ -83,6 +83,16 @@ impl<T, E: Error> Warn for Result<T, E> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> Warn for Option<T> {
 | 
				
			||||||
 | 
					    type Value = T;
 | 
				
			||||||
 | 
					    fn or_warn(self, msg: &str) -> Option<T> {
 | 
				
			||||||
 | 
					        self.or_else(|| {
 | 
				
			||||||
 | 
					            eprintln!("{}", msg);
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A mutable handler for text warnings.
 | 
					/// A mutable handler for text warnings.
 | 
				
			||||||
/// Approach 3.
 | 
					/// Approach 3.
 | 
				
			||||||
pub trait WarningHandler {
 | 
					pub trait WarningHandler {
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,7 @@ cc = meson.get_compiler('c')
 | 
				
			|||||||
deps = [
 | 
					deps = [
 | 
				
			||||||
#  dependency('glib-2.0', version: '>=2.26.0'),
 | 
					#  dependency('glib-2.0', version: '>=2.26.0'),
 | 
				
			||||||
  dependency('gio-2.0', version: '>=2.26.0'),
 | 
					  dependency('gio-2.0', version: '>=2.26.0'),
 | 
				
			||||||
 | 
					  dependency('gnome-desktop-3.0', version: '>=3.0'),
 | 
				
			||||||
  dependency('gtk+-3.0', version: '>=3.0'),
 | 
					  dependency('gtk+-3.0', version: '>=3.0'),
 | 
				
			||||||
  dependency('libcroco-0.6'),
 | 
					  dependency('libcroco-0.6'),
 | 
				
			||||||
  dependency('wayland-client', version: '>=1.14'),
 | 
					  dependency('wayland-client', version: '>=1.14'),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										117
									
								
								src/popover.rs
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/popover.rs
									
									
									
									
									
								
							@ -4,7 +4,8 @@ use gio;
 | 
				
			|||||||
use gtk;
 | 
					use gtk;
 | 
				
			||||||
use std::ffi::CString;
 | 
					use std::ffi::CString;
 | 
				
			||||||
use ::layout::c::{ Bounds, EekGtkKeyboard };
 | 
					use ::layout::c::{ Bounds, EekGtkKeyboard };
 | 
				
			||||||
use ::locale::{ Translation, compare_current_locale };
 | 
					use ::locale;
 | 
				
			||||||
 | 
					use ::locale::{ OwnedTranslation, Translation, compare_current_locale };
 | 
				
			||||||
use ::locale_config::system_locale;
 | 
					use ::locale_config::system_locale;
 | 
				
			||||||
use ::manager;
 | 
					use ::manager;
 | 
				
			||||||
use ::resources;
 | 
					use ::resources;
 | 
				
			||||||
@ -17,6 +18,7 @@ use glib::variant::ToVariant;
 | 
				
			|||||||
use gtk::PopoverExt;
 | 
					use gtk::PopoverExt;
 | 
				
			||||||
use gtk::WidgetExt;
 | 
					use gtk::WidgetExt;
 | 
				
			||||||
use std::io::Write;
 | 
					use std::io::Write;
 | 
				
			||||||
 | 
					use ::logging::Warn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod variants {
 | 
					mod variants {
 | 
				
			||||||
    use glib;
 | 
					    use glib;
 | 
				
			||||||
@ -94,7 +96,7 @@ mod variants {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder {
 | 
					fn make_menu_builder(inputs: Vec<(&str, OwnedTranslation)>) -> gtk::Builder {
 | 
				
			||||||
    let mut xml: Vec<u8> = Vec::new();
 | 
					    let mut xml: Vec<u8> = Vec::new();
 | 
				
			||||||
    writeln!(
 | 
					    writeln!(
 | 
				
			||||||
        xml,
 | 
					        xml,
 | 
				
			||||||
@ -194,6 +196,82 @@ fn get_current_layout(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Translates all provided layout names according to current locale,
 | 
				
			||||||
 | 
					/// for the purpose of display (i.e. errors will be caught and reported)
 | 
				
			||||||
 | 
					fn translate_layout_names(layouts: &Vec<LayoutId>) -> Vec<OwnedTranslation> {
 | 
				
			||||||
 | 
					    // This procedure is rather ugly...
 | 
				
			||||||
 | 
					    // Xkb lookup *must not* be applied to non-system layouts,
 | 
				
			||||||
 | 
					    // so both translators can't be merged into one lookup table,
 | 
				
			||||||
 | 
					    // therefore must be done in two steps.
 | 
				
			||||||
 | 
					    // `XkbInfo` being temporary also means
 | 
				
			||||||
 | 
					    // that its return values must be copied,
 | 
				
			||||||
 | 
					    // forcing the use of `OwnedTranslation`.
 | 
				
			||||||
 | 
					    enum Status {
 | 
				
			||||||
 | 
					        /// xkb names should get all translated here
 | 
				
			||||||
 | 
					        Translated(OwnedTranslation),
 | 
				
			||||||
 | 
					        /// Builtin names need builtin translations
 | 
				
			||||||
 | 
					        Remaining(String),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Attempt to take all xkb names from gnome-desktop's xkb info.
 | 
				
			||||||
 | 
					    let xkb_translator = locale::XkbInfo::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let translated_names = layouts.iter()
 | 
				
			||||||
 | 
					        .map(|id| match id {
 | 
				
			||||||
 | 
					            LayoutId::System { name, kind: _ } => {
 | 
				
			||||||
 | 
					                xkb_translator.get_display_name(name)
 | 
				
			||||||
 | 
					                    .map(|s| Status::Translated(OwnedTranslation(s)))
 | 
				
			||||||
 | 
					                    .unwrap_or_else(|e| {
 | 
				
			||||||
 | 
					                        eprintln!(
 | 
				
			||||||
 | 
					                            "No display name for xkb layout {}: {:?}",
 | 
				
			||||||
 | 
					                            name,
 | 
				
			||||||
 | 
					                            e,
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        Status::Remaining(name.clone())
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            LayoutId::Local(name) => Status::Remaining(name.clone()),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Non-xkb layouts and weird xkb layouts
 | 
				
			||||||
 | 
					    // still need to be looked up in the internal database.
 | 
				
			||||||
 | 
					    let builtin_translations = system_locale()
 | 
				
			||||||
 | 
					        .map(|locale|
 | 
				
			||||||
 | 
					            locale.tags_for("messages")
 | 
				
			||||||
 | 
					                .next().unwrap() // guaranteed to exist
 | 
				
			||||||
 | 
					                .as_ref()
 | 
				
			||||||
 | 
					                .to_owned()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .or_warn("No locale detected")
 | 
				
			||||||
 | 
					        .and_then(|lang| {
 | 
				
			||||||
 | 
					            resources::get_layout_names(lang.as_str())
 | 
				
			||||||
 | 
					                .or_warn(&format!("No translations for locale {}", lang))
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match builtin_translations {
 | 
				
			||||||
 | 
					        Some(translations) => {
 | 
				
			||||||
 | 
					            translated_names
 | 
				
			||||||
 | 
					                .map(|status| match status {
 | 
				
			||||||
 | 
					                    Status::Remaining(name) => {
 | 
				
			||||||
 | 
					                        translations.get(name.as_str())
 | 
				
			||||||
 | 
					                            .unwrap_or(&Translation(name.as_str()))
 | 
				
			||||||
 | 
					                            .to_owned()
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    Status::Translated(t) => t,
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .collect()
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        None => {
 | 
				
			||||||
 | 
					            translated_names
 | 
				
			||||||
 | 
					                .map(|status| match status {
 | 
				
			||||||
 | 
					                    Status::Remaining(name) => OwnedTranslation(name),
 | 
				
			||||||
 | 
					                    Status::Translated(t) => t,
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .collect()
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn show(
 | 
					pub fn show(
 | 
				
			||||||
    window: EekGtkKeyboard,
 | 
					    window: EekGtkKeyboard,
 | 
				
			||||||
    position: Bounds,
 | 
					    position: Bounds,
 | 
				
			||||||
@ -218,46 +296,21 @@ pub fn show(
 | 
				
			|||||||
        .chain(overlay_layouts)
 | 
					        .chain(overlay_layouts)
 | 
				
			||||||
        .collect();
 | 
					        .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let translations = system_locale()
 | 
					    let translated_names = translate_layout_names(&all_layouts);
 | 
				
			||||||
        .map(|locale|
 | 
					 | 
				
			||||||
            locale.tags_for("messages")
 | 
					 | 
				
			||||||
                .next().unwrap() // guaranteed to exist
 | 
					 | 
				
			||||||
                .as_ref()
 | 
					 | 
				
			||||||
                .to_owned()
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .and_then(|lang| resources::get_layout_names(lang.as_str()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let translated_names = all_layouts.iter()
 | 
					 | 
				
			||||||
        .map(LayoutId::get_name);
 | 
					 | 
				
			||||||
    let translated_names: Vec<Translation> = match translations {
 | 
					 | 
				
			||||||
        Some(translations) => {
 | 
					 | 
				
			||||||
            translated_names
 | 
					 | 
				
			||||||
                .map(move |name| {
 | 
					 | 
				
			||||||
                    translations.get(name)
 | 
					 | 
				
			||||||
                        .map(|translation| translation.clone())
 | 
					 | 
				
			||||||
                        .unwrap_or(Translation(name))
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .collect()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        None => {
 | 
					 | 
				
			||||||
            translated_names.map(|name| Translation(name))
 | 
					 | 
				
			||||||
                .collect()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // sorted collection of human and machine names
 | 
					    // sorted collection of human and machine names
 | 
				
			||||||
    let mut human_names: Vec<(Translation, LayoutId)> = translated_names
 | 
					    let mut human_names: Vec<(OwnedTranslation, LayoutId)> = translated_names
 | 
				
			||||||
        .into_iter()
 | 
					        .into_iter()
 | 
				
			||||||
        .zip(all_layouts.clone().into_iter())
 | 
					        .zip(all_layouts.clone().into_iter())
 | 
				
			||||||
        .collect();
 | 
					        .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    human_names.sort_unstable_by(|(tr_a, _), (tr_b, _)| {
 | 
					    human_names.sort_unstable_by(|(tr_a, _), (tr_b, _)| {
 | 
				
			||||||
        compare_current_locale(tr_a.0, tr_b.0)
 | 
					        compare_current_locale(&tr_a.0, &tr_b.0)
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // GVariant doesn't natively support `enum`s,
 | 
					    // GVariant doesn't natively support `enum`s,
 | 
				
			||||||
    // so the `choices` vector will serve as a lookup table.
 | 
					    // so the `choices` vector will serve as a lookup table.
 | 
				
			||||||
    let choices_with_translations: Vec<(String, (Translation, LayoutId))>
 | 
					    let choices_with_translations: Vec<(String, (OwnedTranslation, LayoutId))>
 | 
				
			||||||
        = human_names.into_iter()
 | 
					        = human_names.into_iter()
 | 
				
			||||||
            .enumerate()
 | 
					            .enumerate()
 | 
				
			||||||
                .map(|(i, human_entry)| {(
 | 
					                .map(|(i, human_entry)| {(
 | 
				
			||||||
@ -268,7 +321,7 @@ pub fn show(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let builder = make_menu_builder(
 | 
					    let builder = make_menu_builder(
 | 
				
			||||||
        choices_with_translations.iter()
 | 
					        choices_with_translations.iter()
 | 
				
			||||||
            .map(|(id, (translation, _))| (id.as_str(), translation.clone()))
 | 
					            .map(|(id, (translation, _))| (id.as_str(), (*translation).clone()))
 | 
				
			||||||
            .collect()
 | 
					            .collect()
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
 | 
					 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! CSS data loading */
 | 
					/*! CSS data loading. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::env;
 | 
					use std::env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,6 +83,7 @@ fn get_theme_name(settings: >k::Settings) -> GtkTheme {
 | 
				
			|||||||
        .map_err(|e| {
 | 
					        .map_err(|e| {
 | 
				
			||||||
            match &e {
 | 
					            match &e {
 | 
				
			||||||
                env::VarError::NotPresent => {},
 | 
					                env::VarError::NotPresent => {},
 | 
				
			||||||
 | 
					                // maybe TODO: forward this warning?
 | 
				
			||||||
                e => eprintln!("GTK_THEME variable invalid: {}", e),
 | 
					                e => eprintln!("GTK_THEME variable invalid: {}", e),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            e
 | 
					            e
 | 
				
			||||||
@ -93,13 +94,15 @@ fn get_theme_name(settings: >k::Settings) -> GtkTheme {
 | 
				
			|||||||
        None => GtkTheme {
 | 
					        None => GtkTheme {
 | 
				
			||||||
            name: {
 | 
					            name: {
 | 
				
			||||||
                settings.get_property("gtk-theme-name")
 | 
					                settings.get_property("gtk-theme-name")
 | 
				
			||||||
                    .ok_warn("No theme name")
 | 
					                    // maybe TODO: is this worth a warning?
 | 
				
			||||||
 | 
					                    .or_warn("No theme name")
 | 
				
			||||||
                    .and_then(|value| value.get::<String>())
 | 
					                    .and_then(|value| value.get::<String>())
 | 
				
			||||||
                    .unwrap_or(DEFAULT_THEME_NAME.into())
 | 
					                    .unwrap_or(DEFAULT_THEME_NAME.into())
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            variant: {
 | 
					            variant: {
 | 
				
			||||||
                settings.get_property("gtk-application-prefer-dark-theme")
 | 
					                settings.get_property("gtk-application-prefer-dark-theme")
 | 
				
			||||||
                    .ok_warn("No settings key")
 | 
					                    // maybe TODO: is this worth a warning?
 | 
				
			||||||
 | 
					                    .or_warn("No settings key")
 | 
				
			||||||
                    .and_then(|value| value.get::<bool>())
 | 
					                    .and_then(|value| value.get::<bool>())
 | 
				
			||||||
                    .and_then(|dark_preferred| match dark_preferred {
 | 
					                    .and_then(|dark_preferred| match dark_preferred {
 | 
				
			||||||
                        true => Some("dark".into()),
 | 
					                        true => Some("dark".into()),
 | 
				
			||||||
 | 
				
			|||||||
@ -190,6 +190,11 @@ impl<T> Borrow<Rc<T>> for Pointer<T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait WarningHandler {
 | 
				
			||||||
 | 
					    /// Handle a warning
 | 
				
			||||||
 | 
					    fn handle(&mut self, warning: &str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user