1
# Copyright (C) 2008 Valmantas Paliksa <walmis at balticum-tv dot lt>
2
# Copyright (C) 2008 Tadas Dailyda <tadas at dailyda dot com>
4
# Licensed under the GNU General Public License Version 3
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1
from gi.repository import Notify
2
from gi.repository import Gtk
3
from gi.repository import Gdk
22
4
from blueman.Functions import dprint
23
from blueman.gui.GtkAnimation import AnimBase, BezierController
5
from blueman.gui.GtkAnimation import AnimBase
25
pynotify.init("blueman")
29
12
class Fade(AnimBase):
30
def __init__(self, window):
31
AnimBase.__init__(self, state=OPACITY_START)
34
def state_changed(self, state):
35
self.window.props.opacity = state
37
class NotificationDialog(gtk.MessageDialog):
38
def __init__(self, summary, message, timeout=-1, actions=None, actions_cb=None, pixbuf=None, status_icon=None):
39
gtk.MessageDialog.__init__(self, parent=None, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_NONE, message_format=None)
41
self.bubble = NotificationBubble(summary, message, pixbuf=pixbuf)
45
self.callback = actions_cb
55
self.actions[i] = action_id
56
button = self.add_button(action_name, i)
58
im = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_BUTTON)
60
button.props.image = im
63
self.actions[gtk.RESPONSE_DELETE_EVENT] = "close"
65
self.props.secondary_use_markup = True
68
self.fader = Fade(self)
70
self.props.skip_taskbar_hint = False
72
self.props.title = summary
73
self.props.text = summary
74
self.props.secondary_text = message
76
self.props.window_position = gtk.WIN_POS_CENTER
79
self.set_icon_from_pixbuf(pixbuf)
81
self.connect("response", self.dialog_response)
82
self.props.icon_name = "blueman"
85
def on_enter(widget, event):
86
if self.window == gtk.gdk.window_at_pointer()[0] or not self.entered:
87
self.fader.animate(start=self.fader.get_state(), end=1.0, duration=500)
90
def on_leave(widget, event):
91
if not gtk.gdk.window_at_pointer():
93
self.fader.animate(start=self.fader.get_state(), end=OPACITY_START, duration=500)
95
self.connect("enter-notify-event", on_enter)
96
self.connect("leave-notify-event", on_leave)
99
self.set_opacity(OPACITY_START)
101
self.set_opacity(OPACITY_START)
106
return self.bubble.props.id
108
def dialog_response(self, dialog, response):
110
self.callback(self, self.actions[response])
119
def set_timeout(*args):
122
def add_action(*args):
125
def clear_actions(*args):
128
def set_urgency(*args):
131
def update(self, summary, message):
132
self.props.title = summary
134
self.props.text = summary
135
self.props.secondary_text = message
138
def set_icon_from_pixbuf(self, pixbuf):
139
im = gtk.image_new_from_pixbuf(pixbuf)
144
class NotificationBubble(pynotify.Notification):
145
def __init__(self, summary, message, timeout=-1, actions= None, actions_cb=None, pixbuf=None, status_icon=None):
146
pynotify.Notification.__init__(self, summary, message)
148
def on_notification_closed(n, *args):
149
self.disconnect(closed_sig)
151
actions_cb(n, "closed")
153
def on_action(*args):
154
self.disconnect(closed_sig)
158
self.set_icon_from_pixbuf(pixbuf)
161
for action in actions:
162
self.add_action(action[0], action[1], on_action)
163
self.add_action("default", "Default Action", on_action)
165
closed_sig = self.connect("closed", on_notification_closed)
167
self.set_timeout(timeout)
169
screen, area, orientation = status_icon.get_geometry()
170
self.set_hint("x", area.x + area.width/2)
171
self.set_hint("y", area.y + area.height/2)
13
def __init__(self, window):
14
AnimBase.__init__(self, state=OPACITY_START)
17
def state_changed(self, state):
18
self.window.props.opacity = state
21
class NotificationDialog(Gtk.MessageDialog):
22
def __init__(self, summary, message, timeout=-1, actions=None, actions_cb=None, pixbuf=None, status_icon=None):
23
GObject.GObject.__init__(self, parent=None, flags=0, type=Gtk.MessageType.QUESTION,
24
buttons=Gtk.ButtonsType.NONE, message_format=None)
26
self.bubble = NotificationBubble(summary, message, pixbuf=pixbuf)
30
self.callback = actions_cb
40
self.actions[i] = action_id
41
button = self.add_button(action_name, i)
43
im = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.BUTTON)
45
button.props.image = im
48
self.actions[Gtk.ResponseType.DELETE_EVENT] = "close"
50
self.props.secondary_use_markup = True
53
self.fader = Fade(self)
55
self.props.skip_taskbar_hint = False
57
self.props.title = summary
58
self.props.text = summary
59
self.props.secondary_text = message
61
self.props.window_position = Gtk.WindowPosition.CENTER
64
self.set_icon_from_pixbuf(pixbuf)
66
self.connect("response", self.dialog_response)
67
self.props.icon_name = "blueman"
71
def on_enter(widget, event):
72
if self.window == Gdk.Window.at_pointer()[0] or not self.entered:
73
self.fader.animate(start=self.fader.get_state(), end=1.0, duration=500)
76
def on_leave(widget, event):
77
if not Gdk.Window.at_pointer():
79
self.fader.animate(start=self.fader.get_state(), end=OPACITY_START, duration=500)
81
self.connect("enter-notify-event", on_enter)
82
self.connect("leave-notify-event", on_leave)
84
self.set_opacity(OPACITY_START)
86
self.set_opacity(OPACITY_START)
91
return self.bubble.props.id
93
def dialog_response(self, dialog, response):
95
self.callback(self, self.actions[response])
101
def set_hint_int32(*args):
104
def set_timeout(*args):
107
def add_action(*args):
110
def clear_actions(*args):
113
def set_urgency(*args):
116
def update(self, summary, message):
117
self.props.title = summary
119
self.props.text = summary
120
self.props.secondary_text = message
123
def set_icon_from_pixbuf(self, pixbuf):
124
im = Gtk.Image.new_from_pixbuf(pixbuf)
129
class NotificationBubble(Notify.Notification):
130
def __new__(cls, summary, message, timeout=-1, actions=None, actions_cb=None, pixbuf=None, status_icon=None):
131
self = Notify.Notification.new(summary, message, None)
133
def on_notification_closed(n, *args):
134
self.disconnect(closed_sig)
136
actions_cb(n, "closed")
138
def on_action(n, action, *args):
139
self.disconnect(closed_sig)
140
actions_cb(n, action)
143
self.set_icon_from_pixbuf(pixbuf)
146
for action in actions:
147
self.add_action(action[0], action[1], on_action, None)
148
self.add_action("default", "Default Action", on_action, None)
150
closed_sig = self.connect("closed", on_notification_closed)
152
self.set_timeout(timeout)
154
_, screen, area, orientation = status_icon.get_geometry()
155
self.set_hint_int32("x", area.x + area.width / 2)
156
self.set_hint_int32("y", area.y + area.height / 2)
179
166
class Notification(object):
181
def actions_supported():
182
return "actions" in pynotify.get_server_caps()
184
def __new__(cls, summary, message, timeout=-1, actions= None, actions_cb=None, pixbuf=None, status_icon=None):
185
if not "actions" in pynotify.get_server_caps():
187
return NotificationDialog(summary, message, timeout, actions, actions_cb, pixbuf, status_icon)
189
return NotificationBubble(summary, message, timeout, actions, actions_cb, pixbuf, status_icon)
168
def actions_supported():
169
return "actions" in Notify.get_server_caps()
171
def __new__(cls, summary, message, timeout=-1, actions=None, actions_cb=None, pixbuf=None, status_icon=None):
172
if not "actions" in Notify.get_server_caps():
173
if actions is not None:
174
return NotificationDialog(summary, message, timeout, actions, actions_cb, pixbuf, status_icon)
176
return NotificationBubble(summary, message, timeout, actions, actions_cb, pixbuf, status_icon)