notification-sidebar.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # Written by Adnan Shameem
  2. # License: CC0 - do whatever you want with it
  3. # This script relies on xfce-notifyd. It is lightweight and saves the
  4. # notifications in a ~/.cache/xfce4/notifyd/log file which is formatted
  5. # in INI type format.
  6. # To make this script work,
  7. # 1. Install notification-daemon
  8. # 2. Install xfce4-notifyd
  9. # 3. Run either:
  10. # /usr/lib/xfce4/notifyd/xfce4-notifyd
  11. # or
  12. # systemctl --user start xfce4-notifyd
  13. # 4. Run xfce4-notifyd-config and go to Log and Turn ON Notifications
  14. # and then set Log notifications to "always"
  15. # Now get some notifications from your apps.
  16. # Run this script to show them as a sidebar list.
  17. # If you want to toggle the panel, run this with a toggle script like:
  18. # https://gist.github.com/adnan360/8b223bd54a01dc7a20110808aef003b3
  19. # Something like ./python-invert.sh path/to/notification-sidebar.py
  20. # It will invert the panel everytime this is run.
  21. # You can then run this on a button on a panel.
  22. # Would be great for lightweight desktops, such as, jwm, openbox, i3 etc.
  23. # where DE does not have a notification list panel available.
  24. # TODO: Fix height to fill from top to bottom
  25. # Screenshot: https://imgur.com/wah27HZ or http://i63.tinypic.com/1r6poo.png
  26. ## -------- Imports -------- ##
  27. # Python GTK3
  28. import gi
  29. gi.require_version('Gtk', '3.0')
  30. from gi.repository import Gtk
  31. # Especially for getting screen dimensions
  32. from gi.repository import Gdk
  33. # For processing INI
  34. try:
  35. from configparser import ConfigParser
  36. except ImportError:
  37. from ConfigParser import ConfigParser # ver. < 3.0
  38. # For getting full path to home directory
  39. import os
  40. # -------- Classes/Implementation -------- ##
  41. def deletefile(filename):
  42. if os.path.isfile(filename):
  43. os.remove(filename)
  44. # Get/expand real userpath from "~"
  45. # We will keep the xfce notofications log
  46. inipath = os.path.expanduser("~/.cache/xfce4/notifyd/log")
  47. # Panel width
  48. panel_width = 400
  49. # Class to handle multiline list items
  50. class ListBoxRowWithData(Gtk.ListBoxRow):
  51. def __init__(self, data1, data2):
  52. super(Gtk.ListBoxRow, self).__init__()
  53. self.data1 = data1
  54. self.data2 = data2
  55. box = Gtk.VBox(False, 2)
  56. box.set_homogeneous(True)
  57. item_line1 = Gtk.Label()
  58. item_line1.set_markup("<b>"+data1+"</b>")
  59. item_line1.set_line_wrap(True)
  60. box.pack_start(item_line1, False, False, 10)
  61. if data2 != '':
  62. item_line2 = Gtk.Label()
  63. item_line2.set_markup(data2)
  64. item_line2.set_line_wrap(True)
  65. box.pack_start(item_line2, False, False, 0)
  66. self.add(box)
  67. class MyWindow(Gtk.Window):
  68. def __init__(self):
  69. Gtk.Window.__init__(self, title="Notifications")
  70. # Get screen dimensions
  71. s = self.get_screen()
  72. m = s.get_monitor_at_window(s.get_active_window())
  73. monitor = s.get_monitor_geometry(m)
  74. # Size the window
  75. self.move(monitor.width - panel_width,0)
  76. self.set_default_size(panel_width, monitor.height)
  77. main_grid = Gtk.Grid()
  78. self.add(main_grid)
  79. btnquit = Gtk.Button(label="Close")
  80. btnquit.connect("clicked", Gtk.main_quit)
  81. btnclear = Gtk.Button(label="Clear")
  82. btnclear.connect("clicked", self.on_btnclear_clicked)
  83. notif_list = Gtk.ListBox()
  84. notif_scroller = Gtk.ScrolledWindow()
  85. #notif_scroller.set_policy(Gtk.PolicyType.NEVER,
  86. #Gtk.PolicyType.AUTOMATIC)
  87. # Read INI file
  88. inidata = ConfigParser()
  89. # Sometimes some weird characters appear on the INI.
  90. # ", encoding="ISO-8859-1" stops it from crashing.
  91. inidata.read(inipath, encoding="ISO-8859-1")
  92. # Get all sections
  93. sections = inidata.sections()
  94. # Reverse to show the latest ones first
  95. sections.sort(reverse=True)
  96. for section in sections:
  97. notif_list.add(ListBoxRowWithData(section+': '+inidata.get(section, 'summary'), inidata.get(section, 'body')))
  98. #notif_scroller.attach(notif_list, 1, 0, 2, 1)
  99. main_grid.attach(notif_scroller, 1, 0, 2, 1)
  100. notif_scroller.add_with_viewport(notif_list)
  101. main_grid.attach(btnquit, 1, 2, 1, 1)
  102. main_grid.attach_next_to(btnclear, btnquit, Gtk.PositionType.RIGHT, 1, 1)
  103. notif_list.set_hexpand(True)
  104. notif_list.set_vexpand(True)
  105. def on_btnclear_clicked(self, widget):
  106. deletefile(inipath)
  107. Gtk.main_quit()
  108. win = MyWindow()
  109. win.connect("destroy", Gtk.main_quit)
  110. # Close this panel when mouse gets outside of window
  111. win.connect("leave-notify-event", Gtk.main_quit, "")
  112. # Remove taskbar button
  113. win.set_skip_taskbar_hint(True)
  114. win.show_all()
  115. # Remove titlebar
  116. win.get_window().set_decorations(Gdk.WMDecoration.BORDER)
  117. # No decorations/border at all
  118. # Uncomment this if you want no border at all
  119. #win.set_decorated(False)
  120. Gtk.main()