2022-05-12 23:12:06 +02:00
//! # freedesktop-incons
//!
//! This crate provides a [freedesktop icon](https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#implementation_notes) lookup implementation.
//!
//! It exposes a single [`lookup`] function to find icon based on their, `name`, `theme`, `size` and `scale`.
//!
//! ## Example
//!
//! **Simple lookup:**
//!
//! The following snippet get an icon from the default 'hicolor' theme
//! with the default scale (`1`) and the default size (`24`).
//!
//! ```rust
//! # fn main() {
//! use freedesktop_icons::lookup;
//!
//! let icon = lookup("firefox").find();
//! # }
//!```
//!
//! **Complex lookup:**
//!
//! If you have specific requirement for your lookup you can use the provided builder functions:
//!
//! ```rust
//! # fn main() {
//! use freedesktop_icons::lookup;
//!
//! let icon = lookup("firefox")
//! .with_size(48)
//! .with_scale(2)
//! .with_theme("Arc")
//! .find();
//! # }
//!```
use crate ::cache ::CACHE ;
2022-05-12 15:34:02 +02:00
use crate ::theme ::{ try_build_icon_path , THEMES } ;
2022-05-12 14:41:08 +02:00
use std ::path ::PathBuf ;
2022-05-12 23:12:06 +02:00
mod cache ;
mod theme ;
2022-05-12 15:34:02 +02:00
2022-05-12 23:12:06 +02:00
/// The lookup builder struct, holding all the lookup query parameters.
2022-05-12 15:34:02 +02:00
pub struct LookupBuilder < ' a > {
name : & ' a str ,
scale : u16 ,
size : u16 ,
theme : Option < & ' a str > ,
}
2022-05-12 23:12:06 +02:00
/// Build an icon lookup for the given icon name.
///
/// ## Example
/// ```rust
/// # fn main() {
/// use freedesktop_icons::lookup;
///
/// let icon = lookup("firefox").find();
/// # }
pub fn lookup ( name : & str ) -> LookupBuilder {
LookupBuilder ::new ( name )
}
2022-05-12 15:34:02 +02:00
impl < ' a > LookupBuilder < ' a > {
2022-05-12 23:12:06 +02:00
/// Restrict the lookup to the given icon size.
///
/// ## Example
/// ```rust
/// # fn main() {
/// use freedesktop_icons::lookup;
///
/// let icon = lookup("firefox")
/// .with_size(48)
/// .find();
/// # }
2022-05-12 15:34:02 +02:00
pub fn with_size ( mut self , scale : u16 ) -> Self {
self . scale = scale ;
self
2022-05-12 14:41:08 +02:00
}
2022-05-12 23:12:06 +02:00
/// Restrict the lookup to the given scale.
///
/// ## Example
/// ```rust
/// # fn main() {
/// use freedesktop_icons::lookup;
///
/// let icon = lookup("firefox")
/// .with_scale(2)
/// .find();
/// # }
2022-05-12 15:34:02 +02:00
pub fn with_scale ( mut self , size : u16 ) -> Self {
self . size = size ;
self
}
2022-05-12 23:12:06 +02:00
/// Add the given theme to the current lookup :
/// ## Example
/// ```rust
/// # fn main() {
/// use freedesktop_icons::lookup;
///
/// let icon = lookup("firefox")
/// .with_theme("Papirus")
/// .find();
/// # }
2022-05-12 15:34:02 +02:00
pub fn with_theme < ' b : ' a > ( mut self , theme : & ' b str ) -> Self {
self . theme = Some ( theme ) ;
self
}
2022-05-12 23:12:06 +02:00
/// Execute the current lookup
/// if no icon is found in the current theme fallback to
/// `/usr/shar/hicolor` theme and then to `/usr/share/pixmaps`.
pub fn find ( self ) -> Option < PathBuf > {
// Lookup for an icon in the given theme and fallback to 'hicolor' default theme
let icon = self
. theme
. and_then ( | theme | self . lookup_in_theme ( theme ) )
. or_else ( | | self . lookup_in_theme ( " hicolor " ) ) ;
// Return the icon if found
if icon . is_some ( ) {
return icon ;
} ;
// Last chance
try_build_icon_path ( self . name , " /usr/share/pixmaps " )
}
2022-05-12 15:34:02 +02:00
fn new < ' b : ' a > ( name : & ' b str ) -> Self {
Self {
name ,
scale : 1 ,
size : 24 ,
theme : None ,
2022-05-12 14:41:08 +02:00
}
}
2022-05-12 23:12:06 +02:00
// Recursively lookup for icon in the given theme and its parents
fn lookup_in_theme ( & self , theme : & str ) -> Option < PathBuf > {
let cached = CACHE . get ( theme , self . size , self . scale , self . name ) ;
if cached . is_some ( ) {
return cached ;
2022-05-12 15:34:02 +02:00
}
2022-05-12 23:12:06 +02:00
THEMES . get ( theme ) . and_then ( | icon_theme | {
icon_theme
. try_get_icon ( self . name , self . size , self . scale )
. or_else ( | | {
icon_theme
. inherits ( )
. and_then ( | parent | self . lookup_in_theme ( parent ) )
} )
. map ( | icon | {
CACHE . insert ( theme , self . size , self . scale , self . name , & icon ) ;
icon
} )
} )
2022-05-12 15:34:02 +02:00
}
2022-05-12 14:41:08 +02:00
}
#[ cfg(test) ]
mod test {
use crate ::lookup ;
use speculoos ::prelude ::* ;
2022-05-12 15:34:02 +02:00
use std ::path ::PathBuf ;
2022-05-12 14:41:08 +02:00
#[ test ]
2022-05-12 15:34:02 +02:00
fn simple_lookup ( ) {
2022-05-12 23:12:06 +02:00
let firefox = lookup ( " firefox " ) . find ( ) ;
2022-05-12 15:34:02 +02:00
assert_that! ( firefox ) . is_some ( ) ;
}
#[ test ]
fn compare_to_linincon_with_theme ( ) {
2022-05-12 14:41:08 +02:00
let lin_wireshark = linicon ::lookup_icon ( " wireshark " )
. next ( )
. unwrap ( )
. unwrap ( )
. path ;
2022-05-12 15:34:02 +02:00
let wireshark = lookup ( " wireshark " )
. with_size ( 16 )
. with_scale ( 1 )
. with_theme ( " Papirus " )
2022-05-12 23:12:06 +02:00
. find ( ) ;
2022-05-12 14:41:08 +02:00
assert_that! ( wireshark ) . is_some ( ) . is_equal_to ( lin_wireshark )
}
#[ test ]
fn compare_to_linicon_in_pixmap ( ) {
2022-05-12 15:34:02 +02:00
let archlinux_logo = lookup ( " archlinux-logo " )
. with_size ( 16 )
. with_scale ( 1 )
. with_theme ( " Papirus " )
2022-05-12 23:12:06 +02:00
. find ( ) ;
2022-05-12 14:41:08 +02:00
assert_that! ( archlinux_logo )
. is_some ( )
2022-05-12 15:34:02 +02:00
. is_equal_to ( PathBuf ::from ( " /usr/share/pixmaps/archlinux-logo.png " ) ) ;
2022-05-12 14:41:08 +02:00
}
}