use std::env;
use std::collections::HashSet;
use std::borrow::Cow;
extern crate dbus;
use dbus::{Connection, BusType, Message, MessageItem, TypeSig};
pub mod server;
pub fn exe_name() -> String
{
let exe = env::current_exe().unwrap();
exe.file_name().unwrap().to_str().unwrap().to_string()
}
pub struct Notification
{
pub appname: String,
pub summary: String,
pub body: String,
pub icon: String,
pub hints: HashSet<NotificationHint>,
pub actions: Vec<String>,
pub timeout: i32
}
#[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(i32), Custom(String,String)
}
impl Notification
{
pub fn new() -> Notification
{
Notification {
appname: exe_name(),
summary: String::new(),
body: String::new(),
icon: String::new(),
hints: HashSet::new(),
actions: Vec::new(),
timeout: -1
}
}
pub fn appname(&mut self, appname:&str) -> &mut Notification
{
self.appname = appname.to_string();
self
}
pub fn summary(&mut self, summary:&str) -> &mut Notification
{
self.summary = summary.to_string();
self
}
pub fn body(&mut self, body:&str) -> &mut Notification
{
self.body = body.to_string();
self
}
pub fn icon(&mut self, icon:&str) -> &mut Notification
{
self.icon = icon.to_string();
self
}
pub fn hint(&mut self, hint:NotificationHint) -> &mut Notification
{
self.hints.insert(hint);
self
}
pub fn timeout(&mut self, timeout: i32) -> &mut Notification
{
self.timeout = timeout;
self
}
pub fn actions(&mut self, actions:Vec<String>) -> &mut Notification
{
self.actions = actions;
self
}
pub fn action(&mut self, identifier:&str, label:&str) -> &mut Notification
{
self.actions.push(identifier.to_string());
self.actions.push(label.to_string());
self
}
pub fn finalize(&self) -> Notification
{
Notification {
appname: self.appname.clone(),
summary: self.summary.clone(),
body: self.body.clone(),
icon: self.icon.clone(),
hints: self.hints.clone(),
actions: self.actions.clone(),
timeout: self.timeout.clone(),
}
}
fn pack_hints(&self) -> MessageItem
{
if self.hints.len() > 0 {
let mut hints = vec![];
for hint in self.hints.iter(){
let entry:(String,String) = match hint {
&NotificationHint::ActionIcons(ref value) => ("action-icons".to_string(), format!("{}", value)), &NotificationHint::Category(ref value) => ("category".to_string(), value.clone()),
&NotificationHint::DesktopEntry(ref value) => ("desktop-entry".to_string(), value.clone()),
&NotificationHint::ImagePath(ref value) => ("image-path".to_string(), value.clone()),
&NotificationHint::Resident(ref value) => ("resident".to_string(), format!("{}", value)), &NotificationHint::SoundFile(ref value) => ("sound-file".to_string(), value.clone()),
&NotificationHint::SoundName(ref value) => ("sound-name".to_string(), value.clone()),
&NotificationHint::SuppressSound(value) => ("suppress-sound".to_string(), format!("{}", value)),
&NotificationHint::Transient(value) => ("transient".to_string(), format!("{}", value)),
&NotificationHint::X(value) => ("x".to_string(), format!("{}", value)),
&NotificationHint::Y(value) => ("y".to_string(), format!("{}", value)),
&NotificationHint::Urgency(value) => ("urgency".to_string(), format!("{}", value)),
_ => ("Foo".to_string(),"bar".to_string())
};
hints.push( MessageItem::DictEntry(
Box::new(MessageItem::Str(entry.0)),
Box::new(MessageItem::Variant( Box::new(MessageItem::Str(entry.1))))
));
}
return MessageItem::new_array(hints);
}
return MessageItem::new_array(vec![
MessageItem::DictEntry(
Box::new(MessageItem::Str("".to_string())),
Box::new(MessageItem::Variant( Box::new(MessageItem::Str("".to_string()))))
)
]);
}
fn pack_actions(&self) -> MessageItem
{
if self.actions.len() > 0 {
let mut actions = vec![];
for action in self.actions.iter()
{
actions.push(MessageItem::Str(action.to_string()))
}
return MessageItem::new_array(actions);
}
return MessageItem::new_array(vec![ MessageItem::Str("".to_string()) ]);
}
pub fn show(&self) -> u32
{
let mut message = Message::new_method_call(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"Notify").unwrap();
message.append_items(&[
MessageItem::Str(self.appname.to_string()), MessageItem::UInt32(0), MessageItem::Str(self.icon.to_string()), MessageItem::Str(self.summary.to_string()), MessageItem::Str(self.body.to_string()), self.pack_actions() , self.pack_hints(), MessageItem::Int32(self.timeout) ]);
let connection = Connection::get_private(BusType::Session).unwrap();
let mut r = connection.send_with_reply_and_block(message, 2000).unwrap();
if let Some(&MessageItem::UInt32(ref id)) = r.get_items().get(0) { return *id }
else {return 0}
}
pub fn show_debug(&self) -> u32
{
println!("Notification:\n{}: ({}) {} \"{}\"\n", self.appname, self.icon, self.summary, self.body);
self.show()
}
pub fn get_capabilities() -> Vec<String>
{
let mut capabilities = vec![];
let message = Message::new_method_call(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"GetCapabilities").unwrap();
let connection = Connection::get_private(BusType::Session).unwrap();
let mut r = connection.send_with_reply_and_block(message, 2000).unwrap();
if let Some(&MessageItem::Array(ref items, Cow::Borrowed("s"))) = r.get_items().get(0) {
for item in items.iter(){
if let &MessageItem::Str(ref cap) = item{
capabilities.push(cap.clone());
}
}
}
return capabilities;
}
}