Solaar/lib/logitech_receiver/notify.py

107 lines
4.1 KiB
Python

# -*- python-mode -*-
## Copyright (C) 2024 Solaar contributors
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import logging
logger = logging.getLogger(__name__)
try:
import gi
gi.require_version('Notify', '0.7')
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk, Notify # this import is allowed to fail making the entire feature unavailable
available = True
except (ValueError, ImportError):
available = False
if available:
# cache references to shown notifications here to allow reuse
_notifications = {}
def init():
"""Init the notifications system."""
global available
if available:
if not Notify.is_initted():
if logger.isEnabledFor(logging.INFO):
logger.info('starting desktop notifications')
try:
return Notify.init('solaar') # replace with better name later
except Exception:
logger.exception('initializing desktop notifications')
available = False
return available and Notify.is_initted()
def uninit():
if available and Notify.is_initted():
if logger.isEnabledFor(logging.INFO):
logger.info('stopping desktop notifications')
_notifications.clear()
Notify.uninit()
def show(dev, message, icon=None):
"""Show a notification with title and text."""
if available and (Notify.is_initted() or init()):
summary = dev.name
n = _notifications.get(summary) # reuse notification of same name
if n is None:
n = _notifications[summary] = Notify.Notification()
icon_name = device_icon_name(dev.name, dev.kind) if icon is None else icon
n.update(summary, message, icon_name)
n.set_urgency(Notify.Urgency.NORMAL)
n.set_hint('desktop-entry', GLib.Variant('s', 'solaar')) # replace with better name late
try:
# if logger.isEnabledFor(logging.DEBUG):
# logger.debug("showing %s", n)
n.show()
except Exception:
logger.exception('showing %s', n)
_ICON_LISTS = {}
def device_icon_list(name='_', kind=None):
icon_list = _ICON_LISTS.get(name)
if icon_list is None:
# names of possible icons, in reverse order of likelihood
# the theme will hopefully pick up the most appropriate
icon_list = ['preferences-desktop-peripherals']
if kind:
if str(kind) == 'numpad':
icon_list += ('input-keyboard', 'input-dialpad')
elif str(kind) == 'touchpad':
icon_list += ('input-mouse', 'input-tablet')
elif str(kind) == 'trackball':
icon_list += ('input-mouse', )
elif str(kind) == 'headset':
icon_list += ('audio-headphones', 'audio-headset')
icon_list += ('input-' + str(kind), )
_ICON_LISTS[name] = icon_list
return icon_list
def device_icon_name(name, kind=None):
_default_theme = Gtk.IconTheme.get_default()
icon_list = device_icon_list(name, kind)
for n in reversed(icon_list):
if _default_theme.has_icon(n):
return n
else:
init = lambda: False
uninit = lambda: None
show = lambda dev, reason=None: None