Rolf of Saxony
Rolf of Saxony

Reputation: 22443

Python display a notification with a visible timeout

Please note: this is a self answered question for reference.

Using Python how does one display a notification:
a) with a timeout and
b) have the timeout visibly countdown.

Upvotes: 1

Views: 1936

Answers (1)

Rolf of Saxony
Rolf of Saxony

Reputation: 22443

Update: Just 2 weeks after posting this, I updated to Mint 19 (Ubuntu 18.04) the result, the timer function described below has vanished in the Standard Notification. I can only suppose that the move to GTK+3 has virtually hidden the timer. It is there but barely visible.
Choosing Notification style Nodoka or Coco in Control Centre --> Popup Notifications, does display the timer properly.
End Update

Using the standard notification modules notify2 and Notify in the gi.repository, one simply has to add an action, even though you have no intention of using it.
Note: there appears to be no documented reason for this, that I have found.
In addition to a close button being added to the notification, it also supplies a clockface that reduces based on the timeout supplied.
for notify2:

import notify2

class Notify():
    def mess_callback():
        pass

    def __init__(self,parent,caption,msg,timeout=None,urgency=None):
        if timeout != None: pass
        else: timeout = 0 # message should not timeout

        if urgency: pass
        else: urgency = 0

        img = '/home/rolf/MyApp.png'
        caps = notify2.get_server_caps()    
        mess = notify2.Notification(caption,msg,img) # passing an image is optional
        mess.set_timeout(timeout) #milliseconds
        mess.set_urgency(urgency) #0-Low, 1-Normal, 2-Critical
        # Without the following `add_action` option, No countdown to the time out is shown
        if timeout != 0 and 'actions' in caps:
            mess.add_action("close","Close",self.mess_callback,None) #Show the countdown to close
        mess.show()

if __name__ == "__main__":
    notify2.init("MyApp") #Register MyApp

    Notify(None,"Error","This message is not timed and has to be manually cancelled")
    Notify(None,"Error 2","This message will timeout after the default value",timeout=-1)
    Notify(None,"Information","An Unimportant message",timeout=20000,urgency=0)
    Notify(None,"Attention","An Important message",timeout=20000,urgency=1)
    Notify(None,"Emergency","A Critical message",timeout=20000,urgency=2)

    notify2.uninit() #Un-register

Using Notify in the gi.repository:

import gi
gi.require_version('Notify', '0.7')
from gi.repository import Notify

class Message():
    def mess_callback():
        pass

    def __init__(self,parent,caption,msg,timeout=None,urgency=None):
        if timeout != None: pass
        else: timeout = 0 # message should not timeout

        if urgency: pass
        else: urgency = 0

        img = '/home/rolf/MyApp.png'
        caps = Notify.get_server_caps()    
        mess = Notify.Notification.new(caption, msg, img) # passing an image is optional
        mess.set_timeout(timeout) #milliseconds
        mess.set_urgency(urgency) #0-Low, 1-Normal, 2-Critical
        # Without the following `add_action` option, No countdown to the time out is shown
        if timeout != 0 and 'actions' in caps:
            mess.add_action("close","Close",self.mess_callback,None) #Show the countdown to close
        mess.show()

if __name__ == "__main__":
    Notify.init("MyApp") #Register MyApp

    Message(None,"Error","This message is not timed and has to be manually cancelled")
    Message(None,"Error 2","This message will timeout after the default value",timeout=-1)
    Message(None,"Information","An Unimportant message",timeout=20000,urgency=0)
    Message(None,"Attention","An Important message",timeout=20000,urgency=1)
    Message(None,"Emergency","A Critical message",timeout=20000,urgency=2)

enter image description here

Upvotes: 2

Related Questions