7

I am learning how to use gtk notifications, and it seems that any output display via the notification bubble has a maximum overflow size, probably 10 lines or so. So, if the message I want to show is more than that, it gets suppressed. Is there any way to force display the entire message without anything getting suppressed?

I am using notifyOSD, by the way.

  • You can use zenity for longer messages. notifyosd only suitable for short notifications – Sergiy Kolodyazhnyy Jul 21 '16 at 3:08
  • @Serg Zenity is a good solution for command-line executions, but I have aboslutely no idea how to use it in a python script. Any example would be nice. – Razor Jul 21 '16 at 3:24
  • Python can do everything that command-line can do. I'll post an example in a few minutes – Sergiy Kolodyazhnyy Jul 21 '16 at 3:29
9

I posted this a while ago on a (now) deleted Q/A. Maybe it is useful to you.


A patch to allow (very) long messages

The "patch" below will allow you to have notifications as long as it takes on your desktop:

In case of (very) long notifications, instead of this:

enter image description here

you will see this:

enter image description here

The duration of the message is automatically set to the length of the text.

What it does

Notifications, send by notify-osd (notify-send), are limited to appr. 120 characters.
The solution "listens" to sent messages, using dbus-monitor. If a message exceeds the 120 characters, it takes over the messages and uses "its own" message window to display the notification, as shown above.

The scripts

  1. The setup exists of two sections; de "listen-" script, which intercepts the notifications:

    #!/bin/bash
    
    currdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    
    dbus-monitor "interface='org.freedesktop.Notifications'" |\
     grep --line-buffered "string" |\
     grep --line-buffered -e method -e ":" -e '""' -e urgency -e notify -v |\
     grep --line-buffered '.*(?=string)|(?<=string).*' -oPi |\
     grep --line-buffered -v '^\s*$' |\
     xargs -I '{}' $currdir/message {}
    

    Copy the script into an empty file and save it as catch_notifs.sh

  2. The script that creates the replacement- notifications:

    #!/usr/bin/env python3
    import subprocess
    import os
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import GObject, Gtk, Gdk, Pango
    from threading import Thread
    import time
    import sys
    
    text = sys.argv[1]
    length = len(text)
    showtime = length/20
    
    def get_screen():
        scr = [s.split("x") for s in subprocess.check_output([
            "xrandr"]).decode("utf-8").split() if "+0+0" in s][0]
        return int(scr[0]) -450
    
    class Splash(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="splashtitle")
            maingrid = Gtk.Grid()
            self.add(maingrid)
            maingrid.set_border_width(20)
            label = Gtk.Label(text)
            label.set_line_wrap(True)
            label.set_max_width_chars(45)
            label.modify_font(Pango.FontDescription('Ubuntu 11'))
            maingrid.attach(label, 0, 0, 1, 1)
            self.stop = Thread(target=self.close_window)
            self.stop.start()
    
        def close_window(self):
            time.sleep(showtime)
            Gtk.main_quit()
    
    def splashwindow():
        window = Splash()
        window.set_decorated(False)
        window.set_resizable(False)
        window.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0,0,0,1))
        window.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse("white"))
        # window.set_opacity(0.8)
        window.move(get_screen(), 80)
        window.set_keep_above(True)
        window.show_all()
        window.set_default_size(200, 500)
        GObject.threads_init()
        Gtk.main()
    
    if len(text) > 120:
        subprocess.Popen(["pkill", "notify-osd"])
        splashwindow()
    

    Copy the script above into an empty file, save it as (exactly!) message (no extension) and make it executable.

  3. Store both scripts in one and the same directory.
  4. Test- run the script by the command (from a terminal window):

    /bin/bash /path/to/catch_notifs.sh
    

    (keep it running)

    You can test the setup by running (in another terminal):

    notify-send '<long_text>'
    
  5. If all works fine, add it to Startup Applications: Dash > Startup Applications > Add. Add the command:

    /bin/bash /path/to/catch_notifs.sh
    

And it should work :)

  • you just keep amazing us , ^_^b – Sergiy Kolodyazhnyy Jul 21 '16 at 8:44
  • @Jacob Vlijm Hey, thanks! That does display longer text, but I am still facing a problem because now I want to display a tabular data (containing alphanumerics only) created using tabulate. This keeps giving me an error about xargs and missing double quotes, I have no idea why, and your code exits and notify-osd takes over so text is suppressed again. Could you please look into this? – Razor Jul 24 '16 at 3:00
  • @Razor your question mentions nothing about tabular data, if that would have been important, it should have been in the question! I can look at it, but will not be within a few days. – Jacob Vlijm Jul 24 '16 at 7:21
  • @Jacob Vlijm Sorry, you are right, I should have included that. The table is just plaintext , so I figured if there was a way to display longer text, that would take care of the table too. I will update my question accordingly, with a sample output of what the data looks like. Appreciate your help :) – Razor Jul 24 '16 at 14:04
  • @Razor I wouldn't say "updating" (actually changing) the question is the right thing to do. It is a new question. The current question only mentions lenght in lines. Keeping tabbed layout in order is quite different. – Jacob Vlijm Jul 24 '16 at 14:06
4

As I've noted in the comments , notify-osd is not very suitable for extensive messages and one should prefer zenity instead.

Simple example of usage would be spawning zenity dialog via subprocess.call([COMMAND,OPTIONS])

import subprocess 

text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
command=['zenity', '--info', '--text="' +text + '"', '--width=250', '--height=300' ]
subprocess.call(command)

Very simple example. With something that requires checking exit status, like questions , you might wanna use try - except - else structure

import subprocess 

text='Do you want to use Zenity?'
command=['zenity', '--question', 
         '--text="' +text + '"',
         '--width=250', '--height=300' ]


try:
    stdout = subprocess.check_call(command)

except subprocess.CalledProcessError:
    pass # if return sttus is non-zero, do something here

else:
    # if exit status was 0 , we do something here
    print "Yes, I want to use Zenity too"

If you want something more advanced, probably consider learning one of the graphic toolkits like PyQt or Gtk.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.