#[cfg(all(unix, not(target_os = "macos")))]
use dbus::MessageItem;
use super::NotificationUrgency;
#[cfg(all(unix, not(target_os = "macos")))]
use util::*;
pub const ACTION_ICONS:&'static str = "action-icons";
pub const CATEGORY:&'static str = "category";
pub const DESKTOP_ENTRY:&'static str = "desktop-entry";
pub const IMAGE_PATH:&'static str = "image-path";
pub const RESIDENT:&'static str = "resident";
pub const SOUND_FILE:&'static str = "sound-file";
pub const SOUND_NAME:&'static str = "sound-name";
pub const SUPPRESS_SOUND:&'static str = "suppress-sound";
pub const TRANSIENT:&'static str = "transient";
pub const X:&'static str = "x";
pub const Y:&'static str = "y";
pub const URGENCY:&'static str = "urgency";
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub enum NotificationHint
{ ActionIcons(bool),
Category(String),
DesktopEntry(String),
ImagePath(String),
Resident(bool),
SoundFile(String),
SoundName(String),
SuppressSound(bool),
Transient(bool),
X(i32),
Y(i32),
Urgency(NotificationUrgency),
Custom(String,String),
CustomInt(String, i32),
Invalid }
impl NotificationHint {
pub fn as_bool(&self) -> Option<bool> {
match *self {
NotificationHint::ActionIcons(inner) |
NotificationHint::Resident(inner) |
NotificationHint::SuppressSound(inner) |
NotificationHint::Transient(inner) => Some(inner),
_ => None
}
}
pub fn as_i32(&self) -> Option<i32> {
match *self {
NotificationHint::X(inner) |
NotificationHint::Y(inner) => Some(inner),
_ => None
}
}
pub fn as_str(&self) -> Option<&str> {
match *self {
NotificationHint::DesktopEntry(ref inner) |
NotificationHint::ImagePath(ref inner) |
NotificationHint::SoundFile(ref inner) |
NotificationHint::SoundName(ref inner) => Some(inner),
_ => None
}
}
}
pub fn hint_from_key_val(name: &str, value: &str) -> Result<NotificationHint, String>{
use NotificationHint as Hint;
match (name,value){
(ACTION_ICONS,val) => val.parse::<bool>().map(Hint::ActionIcons).map_err(|e|e.to_string()),
(CATEGORY, val) => Ok(Hint::Category(val.to_owned())),
(DESKTOP_ENTRY, val) => Ok(Hint::DesktopEntry(val.to_owned())),
(IMAGE_PATH, val) => Ok(Hint::ImagePath(val.to_owned())),
(RESIDENT, val) => val.parse::<bool>().map(Hint::Resident).map_err(|e|e.to_string()),
(SOUND_FILE, val) => Ok(Hint::SoundFile(val.to_owned())),
(SOUND_NAME, val) => Ok(Hint::SoundName(val.to_owned())),
(SUPPRESS_SOUND, val) => val.parse::<bool>().map(Hint::SuppressSound).map_err(|e|e.to_string()),
(TRANSIENT, val) => val.parse::<bool>().map(Hint::Transient).map_err(|e|e.to_string()),
(X, val) => val.parse::<i32>().map(Hint::X).map_err(|e|e.to_string()),
(Y, val) => val.parse::<i32>().map(Hint::Y).map_err(|e|e.to_string()),
_ => Err(String::from("unknown name"))
}
}
#[cfg(all(unix, not(target_os = "macos")))]
impl<'a> From<&'a NotificationHint> for MessageItem {
fn from(hint: &NotificationHint) -> MessageItem {
let hint:(String,MessageItem) = match *hint {
NotificationHint::ActionIcons(value) => (ACTION_ICONS .to_owned(), MessageItem::Bool(value)), NotificationHint::Category(ref value) => (CATEGORY .to_owned(), MessageItem::Str(value.clone())),
NotificationHint::DesktopEntry(ref value) => (DESKTOP_ENTRY .to_owned(), MessageItem::Str(value.clone())),
NotificationHint::ImagePath(ref value) => (IMAGE_PATH .to_owned(), MessageItem::Str(value.clone())),
NotificationHint::Resident(value) => (RESIDENT .to_owned(), MessageItem::Bool(value)), NotificationHint::SoundFile(ref value) => (SOUND_FILE .to_owned(), MessageItem::Str(value.clone())),
NotificationHint::SoundName(ref value) => (SOUND_NAME .to_owned(), MessageItem::Str(value.clone())),
NotificationHint::SuppressSound(value) => (SUPPRESS_SOUND .to_owned(), MessageItem::Bool(value)),
NotificationHint::Transient(value) => (TRANSIENT .to_owned(), MessageItem::Bool(value)),
NotificationHint::X(value) => (X .to_owned(), MessageItem::Int32(value)),
NotificationHint::Y(value) => (Y .to_owned(), MessageItem::Int32(value)),
NotificationHint::Urgency(value) => (URGENCY .to_owned(), MessageItem::Byte(value as u8)),
NotificationHint::Custom(ref key, ref val) => (key .to_owned(), MessageItem::Str(val.to_owned ())),
NotificationHint::CustomInt(ref key, val) => (key .to_owned(), MessageItem::Int32(val)),
NotificationHint::Invalid => ("invalid" .to_owned(), MessageItem::Str("Invalid".to_owned()))
};
MessageItem::DictEntry(
Box::new(hint.0.into()),
Box::new(MessageItem::Variant( Box::new(hint.1) ))
)
}
}
#[cfg(all(unix, not(target_os = "macos")))]
impl<'a> From<&'a MessageItem> for NotificationHint {
fn from (item: &MessageItem) -> NotificationHint {
match item{
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == CATEGORY => NotificationHint::Category(unwrap_message_str(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == ACTION_ICONS => NotificationHint::ActionIcons(unwrap_message_bool(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == DESKTOP_ENTRY => NotificationHint::DesktopEntry(unwrap_message_str(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == IMAGE_PATH => NotificationHint::ImagePath(unwrap_message_str(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == RESIDENT => NotificationHint::Resident(unwrap_message_bool(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == SOUND_FILE => NotificationHint::SoundFile(unwrap_message_str(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == SOUND_NAME => NotificationHint::SoundName(unwrap_message_str(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == SUPPRESS_SOUND => NotificationHint::SuppressSound(unwrap_message_bool(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == TRANSIENT => NotificationHint::Transient(unwrap_message_bool(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == X => NotificationHint::X(unwrap_message_int(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == Y => NotificationHint::Y(unwrap_message_int(&**value)),
&MessageItem::DictEntry(ref key, ref value) if unwrap_message_str(&**key) == URGENCY => NotificationHint::Urgency(
match unwrap_message_int(&**value){
0 => NotificationUrgency::Low,
2 => NotificationUrgency::Critical,
_ => NotificationUrgency::Normal
}),
&MessageItem::DictEntry(ref key, ref value) => match try_unwrap_message_int(value) {
Some(num) => NotificationHint::CustomInt(unwrap_message_str(&**key), num),
None => NotificationHint::Custom(unwrap_message_str(&**key), unwrap_message_str(&**value)),
},
other => {println!("Invalid {:#?} ", other); NotificationHint::Invalid}
}
}
}
#[cfg(all(test, unix, not(target_os = "macos")))]
mod test{
use super::*;
use super::NotificationHint as Hint;
use NotificationUrgency::*;
use dbus::MessageItem as Item;
#[test]
fn hint_to_item() {
let category = &Hint::Category("testme".to_owned());
let item:Item= category.into();
let test_item= Item::DictEntry(
Box::new(Item::Str("category".into())),
Box::new(Item::Variant( Box::new(Item::Str("testme".into())) ))
);
assert_eq!(item, test_item);
}
#[test]
fn urgency() {
let low = &Hint::Urgency(Low);
let low_item:Item= low.into();
let test_item= Item::DictEntry(
Box::new(Item::Str("urgency".into())),
Box::new(Item::Variant( Box::new(Item::Byte(0))) ));
assert_eq!(low_item, test_item);
}
#[test]
fn simple_hint_to_item() {
let old_hint = &NotificationHint::Custom("foo".into(), "bar".into());
let item:MessageItem = old_hint.into();
let item_ref = &item;
let hint:NotificationHint = item_ref.into();
assert!(old_hint == &hint);
}
}