- Moved some gui logic out of connector
- Added dbus and notification eavesdropping - Added new overlay to show freedesktop notifications - Taught text overlay to piggyback
This commit is contained in:
parent
fdc790155a
commit
1ac75c94f9
9 changed files with 1025 additions and 29 deletions
|
|
@ -382,10 +382,11 @@ class DiscordConnector:
|
|||
self.set_in_room(thisuser["id"], True)
|
||||
elif j["data"]["type"] == 0: # Text channel
|
||||
if self.request_text_rooms_response is not None:
|
||||
if j['data']['position'] >= len(self.request_text_rooms_response) :
|
||||
if j['data']['position'] >= len(self.request_text_rooms_response):
|
||||
# Error. The list of channels has changed since we requested last
|
||||
self.needs_guild_rerequest = 60 * 30
|
||||
logging.error("IndexError getting channel information. Starting again in 30 seconds")
|
||||
logging.error(
|
||||
"IndexError getting channel information. Starting again in 30 seconds")
|
||||
pass
|
||||
else:
|
||||
self.request_text_rooms_response[j['data']
|
||||
|
|
@ -629,12 +630,6 @@ class DiscordConnector:
|
|||
if self.authed:
|
||||
self.set_text_channel(self.text_settings.get_channel())
|
||||
|
||||
if self.voice_overlay.needsredraw:
|
||||
self.voice_overlay.redraw()
|
||||
|
||||
if self.text_overlay and self.text_overlay.needsredraw:
|
||||
self.text_overlay.redraw()
|
||||
|
||||
if len(self.rate_limited_channels) > 0:
|
||||
guild = self.rate_limited_channels.pop()
|
||||
cmd = {
|
||||
|
|
|
|||
|
|
@ -12,14 +12,19 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""Main application class"""
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import dbus
|
||||
import logging
|
||||
import gi
|
||||
import pidfile
|
||||
from .settings_window import MainSettingsWindow
|
||||
from .voice_overlay import VoiceOverlayWindow
|
||||
from .text_overlay import TextOverlayWindow
|
||||
from .notification_overlay import NotificationOverlayWindow
|
||||
from .discord_connector import DiscordConnector
|
||||
from dbus.mainloop.glib import DBusGMainLoop # integration into the main loop
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
# pylint: disable=wrong-import-position,wrong-import-order
|
||||
from gi.repository import Gtk, GLib, Gio # nopep8
|
||||
|
|
@ -39,6 +44,9 @@ class Discover:
|
|||
self.steamos = False
|
||||
self.show_settings_delay = False
|
||||
self.settings = None
|
||||
self.notification_messages = []
|
||||
self.dbus_notification = None
|
||||
self.bus = None
|
||||
|
||||
self.debug_file = debug_file
|
||||
|
||||
|
|
@ -66,6 +74,7 @@ class Discover:
|
|||
self.settings.text_settings.add_connector(self.connection)
|
||||
self.connection.connect()
|
||||
GLib.timeout_add((1000 / 60), self.connection.do_read)
|
||||
GLib.timeout_add((1000 / 20), self.periodic_run)
|
||||
self.rpc_file = rpc_file
|
||||
rpc_file = Gio.File.new_for_path(rpc_file)
|
||||
monitor = rpc_file.monitor_file(0, None)
|
||||
|
|
@ -73,6 +82,51 @@ class Discover:
|
|||
|
||||
Gtk.main()
|
||||
|
||||
def set_dbus_notifications(self, enabled=False):
|
||||
if not self.bus:
|
||||
DBusGMainLoop(set_as_default=True)
|
||||
self.bus = dbus.SessionBus()
|
||||
self.bus.add_match_string_non_blocking(
|
||||
"eavesdrop=true, interface='org.freedesktop.Notifications', member='Notify'")
|
||||
if enabled:
|
||||
if not self.dbus_notification:
|
||||
self.bus.add_message_filter(self.add_notification_message)
|
||||
self.dbus_notification = True
|
||||
|
||||
def periodic_run(self, data=None):
|
||||
if self.voice_overlay.needsredraw:
|
||||
self.voice_overlay.redraw()
|
||||
|
||||
if self.text_overlay and self.text_overlay.needsredraw:
|
||||
self.text_overlay.redraw()
|
||||
|
||||
if self.notification_overlay:
|
||||
if self.notification_overlay.enabled:
|
||||
# This doesn't really belong in overlay or settings
|
||||
now = time.time()
|
||||
newlist = []
|
||||
oldsize = len(self.notification_messages)
|
||||
# Iterate over and remove messages older than 30s
|
||||
for message in self.notification_messages:
|
||||
if message['time'] + self.settings.notification_settings.text_time > now:
|
||||
newlist.append(message)
|
||||
self.notification_messages = newlist
|
||||
# If the list is different than before
|
||||
if oldsize != len(newlist):
|
||||
self.notification_overlay.set_content(
|
||||
self.notification_messages, True)
|
||||
if self.notification_overlay.needsredraw:
|
||||
self.notification_overlay.redraw()
|
||||
return True
|
||||
|
||||
def add_notification_message(self, bus, message):
|
||||
args = message.get_args_list()
|
||||
logging.warning(args)
|
||||
noti = {"title": "%s" % (args[3]), "body": "%s" % (args[4]),
|
||||
"icon": "%s" % (args[2]), "cmd": "%s" % (args[0]), "time": time.time()}
|
||||
self.notification_messages.append(noti)
|
||||
self.notification_overlay.set_content(self.notification_messages, True)
|
||||
|
||||
def do_args(self, data, normal_close):
|
||||
"""
|
||||
Read in arg list from command or RPC and act accordingly
|
||||
|
|
@ -133,8 +187,11 @@ class Discover:
|
|||
|
||||
if self.steamos:
|
||||
self.text_overlay = TextOverlayWindow(self, self.voice_overlay)
|
||||
self.notification_overlay = NotificationOverlayWindow(
|
||||
self, self.text_overlay)
|
||||
else:
|
||||
self.text_overlay = TextOverlayWindow(self)
|
||||
self.notification_overlay = NotificationOverlayWindow(self)
|
||||
self.menu = self.make_menu()
|
||||
self.make_sys_tray_icon(self.menu)
|
||||
self.settings = MainSettingsWindow(self)
|
||||
|
|
@ -262,7 +319,6 @@ def entrypoint():
|
|||
rpc_file = os.path.join(config_dir, "discover_overlay.rpc")
|
||||
debug_file = os.path.join(config_dir, "output.txt")
|
||||
|
||||
|
||||
# Flatpak compat mode
|
||||
|
||||
if "container" in os.environ and os.environ["container"] == "flatpak":
|
||||
|
|
|
|||
|
|
@ -97,21 +97,24 @@ class SurfaceGetter():
|
|||
logging.error("Unknown image type")
|
||||
|
||||
def get_file(self):
|
||||
locations = [os.path.expanduser('~/.local/'), '/usr/']
|
||||
locations = [os.path.expanduser('~/.local/'), '/usr/', '/']
|
||||
for prefix in locations:
|
||||
mixpath = os.path.join(prefix, self.url)
|
||||
image = None
|
||||
try:
|
||||
image = Image.open(os.path.join(prefix, self.url))
|
||||
surface = self.from_pil(image)
|
||||
image = Image.open(mixpath)
|
||||
except ValueError:
|
||||
logging.error("Value Erorr - Unable to read %s", mixpath)
|
||||
except TypeError:
|
||||
logging.error("Type Error - Unable to read %s", mixpath)
|
||||
except PIL.UnidentifiedImageError:
|
||||
logging.error("Unknown image type: %s", mixpath)
|
||||
except FileNotFoundError:
|
||||
logging.error("File not found: %s", mixpath)
|
||||
surface = self.from_pil(image)
|
||||
if surface:
|
||||
self.func(self.identifier, surface)
|
||||
return
|
||||
except ValueError:
|
||||
logging.error("Unable to read %s", self.url)
|
||||
except TypeError:
|
||||
logging.error("Unable to read %s", self.url)
|
||||
except PIL.UnidentifiedImageError:
|
||||
logging.error("Unknown image type")
|
||||
except FileNotFoundError:
|
||||
logging.error("Unable to load file %s", self.url)
|
||||
|
||||
def from_pil(self, image, alpha=1.0):
|
||||
"""
|
||||
|
|
|
|||
422
discover_overlay/notification_overlay.py
Normal file
422
discover_overlay/notification_overlay.py
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
# 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
"""Notification window for text"""
|
||||
import logging
|
||||
import time
|
||||
import re
|
||||
import cairo
|
||||
import gi
|
||||
from .image_getter import get_surface, draw_img_to_rect, get_aspected_size
|
||||
from .overlay import OverlayWindow
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version('PangoCairo', '1.0')
|
||||
# pylint: disable=wrong-import-position,wrong-import-order
|
||||
from gi.repository import Gtk, Pango, PangoCairo # nopep8
|
||||
|
||||
|
||||
class NotificationOverlayWindow(OverlayWindow):
|
||||
"""Overlay window for notifications"""
|
||||
|
||||
def __init__(self, discover, piggyback=None):
|
||||
OverlayWindow.__init__(self, discover, piggyback)
|
||||
self.text_spacing = 4
|
||||
self.content = []
|
||||
self.test_content = [{"icon": "next", "title": "Title1"},
|
||||
{"title": "Title2", "body": "Body", "icon": None},
|
||||
{"icon": "discord", "title": "Title 3", "body": "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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."},
|
||||
{"icon": None, "title": "Title 3", "body": "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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."}]
|
||||
self.text_font = None
|
||||
self.text_size = 13
|
||||
self.text_time = None
|
||||
self.show_icon = None
|
||||
self.pango_rect = Pango.Rectangle()
|
||||
self.pango_rect.width = self.text_size * Pango.SCALE
|
||||
self.pango_rect.height = self.text_size * Pango.SCALE
|
||||
|
||||
self.connected = True
|
||||
self.bg_col = [0.0, 0.6, 0.0, 0.1]
|
||||
self.fg_col = [1.0, 1.0, 1.0, 1.0]
|
||||
self.icons = []
|
||||
self.reverse_order = False
|
||||
self.padding = 10
|
||||
self.border_radius = 5
|
||||
self.limit_width = 100
|
||||
self.testing = False
|
||||
self.icon_size = 64
|
||||
self.icon_pad = 16
|
||||
self.icon_left = True
|
||||
|
||||
self.image_list = {}
|
||||
self.warned_filetypes = []
|
||||
self.set_title("Discover Text")
|
||||
self.redraw()
|
||||
|
||||
def set_padding(self, padding):
|
||||
"""
|
||||
Set the padding between notifications
|
||||
"""
|
||||
self.padding = padding
|
||||
self.needsredraw = True
|
||||
|
||||
def set_border_radius(self, radius):
|
||||
"""
|
||||
Set the radius of the border
|
||||
"""
|
||||
self.border_radius = radius
|
||||
self.needsredraw = True
|
||||
|
||||
def set_icon_size(self, size):
|
||||
"""
|
||||
Set Icon size
|
||||
"""
|
||||
self.icon_size = size
|
||||
self.image_list = {}
|
||||
self.get_all_images()
|
||||
|
||||
def set_icon_pad(self, pad):
|
||||
"""
|
||||
Set padding between icon and message
|
||||
"""
|
||||
self.icon_pad = pad
|
||||
self.needsredraw = True
|
||||
|
||||
def set_icon_left(self, left):
|
||||
self.icon_left = left
|
||||
self.needsredraw = True
|
||||
|
||||
def set_text_time(self, timer):
|
||||
"""
|
||||
Set the duration that a message will be visible for.
|
||||
"""
|
||||
self.text_time = timer
|
||||
|
||||
def set_limit_width(self, limit):
|
||||
"""
|
||||
Set the word wrap limit in pixels
|
||||
"""
|
||||
self.limit_width = limit
|
||||
self.needsredraw = True
|
||||
|
||||
def set_content(self, content, altered):
|
||||
"""
|
||||
Update the list of text messages to show
|
||||
"""
|
||||
self.content = content
|
||||
if altered:
|
||||
self.needsredraw = True
|
||||
self.get_all_images()
|
||||
|
||||
def get_all_images(self):
|
||||
the_list = self.content
|
||||
if self.testing:
|
||||
the_list = self.test_content
|
||||
for line in the_list:
|
||||
icon = line["icon"]
|
||||
if icon and icon not in self.image_list:
|
||||
icon_theme = Gtk.IconTheme.get_default()
|
||||
icon_info = icon_theme.lookup_icon(
|
||||
icon, self.icon_size, Gtk.IconLookupFlags.FORCE_SIZE)
|
||||
if icon_info:
|
||||
get_surface(self.recv_icon,
|
||||
icon_info.get_filename(), icon, self.icon_size)
|
||||
|
||||
def recv_icon(self, identifier, pix):
|
||||
"""
|
||||
Called when image_getter has downloaded an image
|
||||
"""
|
||||
self.image_list[identifier] = pix
|
||||
self.needsredraw = True
|
||||
|
||||
def set_fg(self, fg_col):
|
||||
"""
|
||||
Set default text colour
|
||||
"""
|
||||
self.fg_col = fg_col
|
||||
self.needsredraw = True
|
||||
|
||||
def set_bg(self, bg_col):
|
||||
"""
|
||||
Set background colour
|
||||
"""
|
||||
self.bg_col = bg_col
|
||||
self.needsredraw = True
|
||||
|
||||
def set_show_icon(self, icon):
|
||||
"""
|
||||
Set if icons should be shown inline
|
||||
"""
|
||||
self.show_icon = icon
|
||||
self.needsredraw = True
|
||||
self.get_all_images()
|
||||
|
||||
def set_reverse_order(self, rev):
|
||||
self.reverse_order = rev
|
||||
self.needsredraw = True
|
||||
|
||||
def set_font(self, font):
|
||||
"""
|
||||
Set font used to render text
|
||||
"""
|
||||
self.text_font = font
|
||||
|
||||
self.pango_rect = Pango.Rectangle()
|
||||
font = Pango.FontDescription(self.text_font)
|
||||
self.pango_rect.width = font.get_size() * Pango.SCALE
|
||||
self.pango_rect.height = font.get_size() * Pango.SCALE
|
||||
self.needsredraw = True
|
||||
|
||||
def recv_attach(self, identifier, pix):
|
||||
"""
|
||||
Called when an image has been downloaded by image_getter
|
||||
"""
|
||||
self.icons[identifier] = pix
|
||||
self.needsredraw = True
|
||||
|
||||
def calc_all_height(self):
|
||||
h = 0
|
||||
my_list = self.content
|
||||
if self.testing:
|
||||
my_list = self.test_content
|
||||
for line in my_list:
|
||||
h += self.calc_height(line)
|
||||
if h > 0:
|
||||
h -= self.padding # Remove one unneeded padding
|
||||
return h
|
||||
|
||||
def calc_height(self, line):
|
||||
icon_width = 0
|
||||
icon_pad = 0
|
||||
icon = line['icon']
|
||||
if self.show_icon and icon and icon in self.image_list and self.image_list[icon]:
|
||||
icon_width = self.icon_size
|
||||
icon_pad = self.icon_pad
|
||||
message = ""
|
||||
if 'body' in line and len(line['body']) > 0:
|
||||
m_no_body = "<span>%s</span>\n%s"
|
||||
message = m_no_body % (self.sanitize_string(line["title"]),
|
||||
self.sanitize_string(line['body']))
|
||||
else:
|
||||
m_with_body = "<span>%s</span>"
|
||||
message = m_with_body % (self.sanitize_string(line["title"]))
|
||||
layout = self.create_pango_layout(message)
|
||||
layout.set_auto_dir(True)
|
||||
layout.set_markup(message, -1)
|
||||
attr = layout.get_attributes()
|
||||
width = self.limit_width if self.width > self.limit_width else self.width
|
||||
layout.set_width((Pango.SCALE * (width -
|
||||
(self.border_radius * 4 + icon_width + icon_pad))))
|
||||
layout.set_spacing(Pango.SCALE * 3)
|
||||
if self.text_font:
|
||||
font = Pango.FontDescription(self.text_font)
|
||||
layout.set_font_description(font)
|
||||
text_width, text_height = layout.get_pixel_size()
|
||||
if text_height < icon_width:
|
||||
text_height = icon_width
|
||||
return text_height + (self.border_radius*4) + self.padding
|
||||
|
||||
def overlay_draw(self, _w, context, data=None):
|
||||
"""
|
||||
Draw the overlay
|
||||
"""
|
||||
if self.piggyback:
|
||||
self.piggyback.overlay_draw(w, context, data)
|
||||
if not self.enabled:
|
||||
return
|
||||
self.context = context
|
||||
(width, height) = self.get_size()
|
||||
if not self.piggyback_parent:
|
||||
context.set_antialias(cairo.ANTIALIAS_GOOD)
|
||||
|
||||
# Make background transparent
|
||||
context.set_source_rgba(0.0, 0.0, 0.0, 0.0)
|
||||
context.set_operator(cairo.OPERATOR_SOURCE)
|
||||
context.paint()
|
||||
|
||||
context.save()
|
||||
if self.is_wayland or self.piggyback_parent or self.discover.steamos:
|
||||
# Special case!
|
||||
# The window is full-screen regardless of what the user has selected.
|
||||
# We need to set a clip and a transform to imitate original behaviour
|
||||
# Used in wlroots & gamescope
|
||||
width = self.width
|
||||
height = self.height
|
||||
context.translate(self.pos_x, self.pos_y)
|
||||
context.rectangle(0, 0, width, height)
|
||||
context.clip()
|
||||
|
||||
current_y = height
|
||||
if self.align_vert == 0:
|
||||
current_y = 0
|
||||
if self.align_vert == 1: # Center. Oh god why
|
||||
current_y = (height/2.0) - (self.calc_all_height() / 2.0)
|
||||
tnow = time.time()
|
||||
if self.testing:
|
||||
the_list = self.test_content
|
||||
else:
|
||||
the_list = self.content
|
||||
if self.reverse_order:
|
||||
the_list = reversed(the_list)
|
||||
for line in the_list:
|
||||
col = "#fff"
|
||||
if 'body' in line and len(line['body']) > 0:
|
||||
m_no_body = "<span foreground='%s'>%s</span>\n%s"
|
||||
message = m_no_body % (self.sanitize_string(col),
|
||||
self.sanitize_string(line["title"]),
|
||||
self.sanitize_string(line['body']))
|
||||
else:
|
||||
m_with_body = "<span foreground='%s'>%s</span>"
|
||||
message = m_with_body % (self.sanitize_string(col),
|
||||
self.sanitize_string(line["title"]))
|
||||
current_y = self.draw_text(current_y, message, line["icon"])
|
||||
if current_y <= 0:
|
||||
# We've done enough
|
||||
break
|
||||
context.restore()
|
||||
self.context = None
|
||||
|
||||
def draw_text(self, pos_y, text, icon):
|
||||
"""
|
||||
Draw a text message, returning the Y position of the next message
|
||||
"""
|
||||
|
||||
icon_width = 0
|
||||
icon_pad = 0
|
||||
if self.show_icon and icon and icon in self.image_list and self.image_list[icon]:
|
||||
icon = self.image_list[icon]
|
||||
icon_width = self.icon_size
|
||||
icon_pad = self.icon_pad
|
||||
else:
|
||||
icon = None
|
||||
|
||||
layout = self.create_pango_layout(text)
|
||||
layout.set_auto_dir(True)
|
||||
layout.set_markup(text, -1)
|
||||
attr = layout.get_attributes()
|
||||
|
||||
width = self.limit_width if self.width > self.limit_width else self.width
|
||||
layout.set_width((Pango.SCALE * (width -
|
||||
(self.border_radius * 4 + icon_width + icon_pad))))
|
||||
layout.set_spacing(Pango.SCALE * 3)
|
||||
if self.text_font:
|
||||
font = Pango.FontDescription(self.text_font)
|
||||
layout.set_font_description(font)
|
||||
text_width, text_height = layout.get_pixel_size()
|
||||
self.col(self.bg_col)
|
||||
top = 0
|
||||
if self.align_vert == 2: # Bottom align
|
||||
top = pos_y - (text_height + self.border_radius * 4)
|
||||
else: # Top align
|
||||
top = pos_y
|
||||
if text_height < icon_width:
|
||||
text_height = icon_width
|
||||
shape_height = text_height + self.border_radius * 4
|
||||
shape_width = text_width + self.border_radius*4 + icon_width + icon_pad
|
||||
|
||||
left = 0
|
||||
if self.align_right:
|
||||
left = self.width - shape_width
|
||||
|
||||
self.context.save()
|
||||
# Draw Background
|
||||
self.context.translate(left, top)
|
||||
self.context.rectangle(self.border_radius, 0,
|
||||
shape_width - (self.border_radius*2), shape_height)
|
||||
self.context.rectangle(0, self.border_radius,
|
||||
shape_width, shape_height - (self.border_radius * 2))
|
||||
self.context.fill()
|
||||
self.context.set_operator(cairo.OPERATOR_OVER)
|
||||
# Draw Image
|
||||
if icon:
|
||||
self.context.save()
|
||||
if self.icon_left:
|
||||
self.context.translate(
|
||||
self.border_radius*2, self.border_radius*2)
|
||||
draw_img_to_rect(icon, self.context, 0, 0,
|
||||
icon_width, icon_width)
|
||||
else:
|
||||
self.context.translate(
|
||||
self.border_radius*2 + text_width + icon_pad, self.border_radius*2)
|
||||
draw_img_to_rect(icon, self.context, 0, 0,
|
||||
icon_width, icon_width)
|
||||
self.context.restore()
|
||||
|
||||
self.col(self.fg_col)
|
||||
|
||||
if self.icon_left:
|
||||
self.context.translate(
|
||||
self.border_radius*2 + icon_width + icon_pad, self.border_radius*2)
|
||||
PangoCairo.context_set_shape_renderer(
|
||||
self.get_pango_context(), self.render_custom, None)
|
||||
|
||||
text = layout.get_text()
|
||||
count = 0
|
||||
|
||||
layout.set_attributes(attr)
|
||||
|
||||
PangoCairo.show_layout(self.context, layout)
|
||||
else:
|
||||
self.context.translate(self.border_radius*2, self.border_radius*2)
|
||||
PangoCairo.context_set_shape_renderer(
|
||||
self.get_pango_context(), self.render_custom, None)
|
||||
|
||||
text = layout.get_text()
|
||||
count = 0
|
||||
|
||||
layout.set_attributes(attr)
|
||||
|
||||
PangoCairo.show_layout(self.context, layout)
|
||||
|
||||
self.context.restore()
|
||||
next_y = 0
|
||||
if self.align_vert == 2:
|
||||
next_y = pos_y - (shape_height + self.padding)
|
||||
else:
|
||||
next_y = pos_y + shape_height + self.padding
|
||||
return next_y
|
||||
|
||||
def render_custom(self, ctx, shape, path, _data):
|
||||
"""
|
||||
Draw an inline image as a custom emoticon
|
||||
"""
|
||||
# print(shape.data, self.image_list, self.attachment)
|
||||
if shape.data >= len(self.image_list):
|
||||
logging.warning(f"{shape.data} >= {len(self.image_list)}")
|
||||
return
|
||||
# key is the url to the image
|
||||
key = self.image_list[shape.data]
|
||||
if key not in self.attachment:
|
||||
get_surface(self.recv_attach,
|
||||
key,
|
||||
key, None)
|
||||
return
|
||||
pix = self.attachment[key]
|
||||
(pos_x, pos_y) = ctx.get_current_point()
|
||||
draw_img_to_rect(pix, ctx, pos_x, pos_y - self.text_size, self.text_size,
|
||||
self.text_size, path=path)
|
||||
return True
|
||||
|
||||
def sanitize_string(self, string):
|
||||
"""
|
||||
Sanitize a text message so that it doesn't intefere with Pango's XML format
|
||||
"""
|
||||
string = string.replace("&", "&")
|
||||
string = string.replace("<", "<")
|
||||
string = string .replace(">", ">")
|
||||
string = string.replace("'", "'")
|
||||
string = string.replace("\"", """)
|
||||
return string
|
||||
|
||||
def set_testing(self, testing):
|
||||
self.testing = testing
|
||||
self.needsredraw = True
|
||||
self.get_all_images()
|
||||
510
discover_overlay/notification_settings.py
Normal file
510
discover_overlay/notification_settings.py
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
# 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
"""Notification setting tab on settings window"""
|
||||
import json
|
||||
import logging
|
||||
from configparser import ConfigParser
|
||||
import gi
|
||||
from .settings import SettingsWindow
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
# pylint: disable=wrong-import-position,wrong-import-order
|
||||
from gi.repository import Gtk, Gdk # nopep8
|
||||
|
||||
|
||||
GUILD_DEFAULT_VALUE = "0"
|
||||
|
||||
|
||||
class NotificationSettingsWindow(SettingsWindow):
|
||||
"""Notification setting tab on settings window"""
|
||||
|
||||
def __init__(self, overlay, discover):
|
||||
SettingsWindow.__init__(self, discover)
|
||||
self.overlay = overlay
|
||||
|
||||
self.placement_window = None
|
||||
self.init_config()
|
||||
self.align_x = None
|
||||
self.align_y = None
|
||||
self.monitor = None
|
||||
self.floating = None
|
||||
self.font = None
|
||||
self.bg_col = None
|
||||
self.fg_col = None
|
||||
self.text_time = None
|
||||
self.show_icon = None
|
||||
self.enabled = None
|
||||
self.limit_width = None
|
||||
self.icon_left = None
|
||||
self.padding = None
|
||||
self.icon_padding = None
|
||||
self.icon_size = None
|
||||
self.border_radius = None
|
||||
|
||||
self.set_size_request(400, 200)
|
||||
self.connect("destroy", self.close_window)
|
||||
self.connect("delete-event", self.close_window)
|
||||
if overlay:
|
||||
self.init_config()
|
||||
self.create_gui()
|
||||
|
||||
def present_settings(self):
|
||||
"""
|
||||
Show contents of tab and update lists
|
||||
"""
|
||||
if not self.overlay:
|
||||
return
|
||||
self.show_all()
|
||||
if not self.floating:
|
||||
self.align_x_widget.show()
|
||||
self.align_y_widget.show()
|
||||
self.align_monitor_widget.show()
|
||||
self.align_placement_widget.hide()
|
||||
else:
|
||||
self.align_x_widget.hide()
|
||||
self.align_y_widget.hide()
|
||||
self.align_monitor_widget.show()
|
||||
self.align_placement_widget.show()
|
||||
|
||||
def read_config(self):
|
||||
"""
|
||||
Read in the 'text' section of the config
|
||||
"""
|
||||
if not self.overlay:
|
||||
return
|
||||
config = ConfigParser(interpolation=None)
|
||||
config.read(self.config_file)
|
||||
self.enabled = config.getboolean(
|
||||
"notification", "enabled", fallback=False)
|
||||
self.align_x = config.getboolean(
|
||||
"notification", "rightalign", fallback=True)
|
||||
self.align_y = config.getint("notification", "topalign", fallback=2)
|
||||
self.monitor = config.get("notification", "monitor", fallback="None")
|
||||
self.floating = config.getboolean(
|
||||
"notification", "floating", fallback=False)
|
||||
self.floating_x = config.getint(
|
||||
"notification", "floating_x", fallback=0)
|
||||
self.floating_y = config.getint(
|
||||
"notification", "floating_y", fallback=0)
|
||||
self.floating_w = config.getint(
|
||||
"notification", "floating_w", fallback=400)
|
||||
self.floating_h = config.getint(
|
||||
"notification", "floating_h", fallback=400)
|
||||
self.font = config.get("notification", "font", fallback=None)
|
||||
self.bg_col = json.loads(config.get(
|
||||
"notification", "bg_col", fallback="[0.0,0.0,0.0,0.5]"))
|
||||
self.fg_col = json.loads(config.get(
|
||||
"notification", "fg_col", fallback="[1.0,1.0,1.0,1.0]"))
|
||||
self.text_time = config.getint(
|
||||
"notification", "text_time", fallback=30)
|
||||
self.show_icon = config.getboolean(
|
||||
"notification", "show_icon", fallback=True)
|
||||
self.reverse_order = config.getboolean(
|
||||
"notification", "rev", fallback=False)
|
||||
self.limit_width = config.getint(
|
||||
"notification", "limit_width", fallback=100)
|
||||
self.icon_left = config.getboolean(
|
||||
"notification", "icon_left", fallback=True)
|
||||
self.icon_padding = config.getint(
|
||||
"notification", "icon_padding", fallback=8)
|
||||
self.icon_size = config.getint(
|
||||
"notification", "icon_size", fallback=32)
|
||||
self.padding = config.getint(
|
||||
"notification", "padding", fallback=8)
|
||||
self.border_radius = config.getint(
|
||||
"notification", "border_radius", fallback=8)
|
||||
|
||||
# Pass all of our config over to the overlay
|
||||
self.overlay.set_enabled(self.enabled)
|
||||
self.overlay.set_align_x(self.align_x)
|
||||
self.overlay.set_align_y(self.align_y)
|
||||
self.overlay.set_monitor(self.get_monitor_index(
|
||||
self.monitor), self.get_monitor_obj(self.monitor))
|
||||
self.overlay.set_floating(
|
||||
self.floating, self.floating_x, self.floating_y, self.floating_w, self.floating_h)
|
||||
self.overlay.set_bg(self.bg_col)
|
||||
self.overlay.set_fg(self.fg_col)
|
||||
self.overlay.set_text_time(self.text_time)
|
||||
self.overlay.set_show_icon(self.show_icon)
|
||||
self.overlay.set_reverse_order(self.reverse_order)
|
||||
self.overlay.set_limit_width(self.limit_width)
|
||||
self.overlay.set_icon_left(self.icon_left)
|
||||
self.overlay.set_icon_size(self.icon_size)
|
||||
self.overlay.set_icon_pad(self.icon_padding)
|
||||
self.overlay.set_padding(self.padding)
|
||||
self.overlay.set_border_radius(self.border_radius)
|
||||
self.discover.set_dbus_notifications(self.enabled)
|
||||
|
||||
def save_config(self):
|
||||
"""
|
||||
Save the current settings to the 'text' section of the config
|
||||
"""
|
||||
config = ConfigParser(interpolation=None)
|
||||
config.read(self.config_file)
|
||||
if not config.has_section("notification"):
|
||||
config.add_section("notification")
|
||||
|
||||
config.set("notification", "rightalign", "%d" % (int(self.align_x)))
|
||||
config.set("notification", "topalign", "%d" % (self.align_y))
|
||||
config.set("notification", "monitor", self.monitor)
|
||||
config.set("notification", "enabled", "%d" % (int(self.enabled)))
|
||||
config.set("notification", "floating", "%s" % (int(self.floating)))
|
||||
config.set("notification", "floating_x", "%s" % (int(self.floating_x)))
|
||||
config.set("notification", "floating_y", "%s" % (int(self.floating_y)))
|
||||
config.set("notification", "floating_w", "%s" % (int(self.floating_w)))
|
||||
config.set("notification", "floating_h", "%s" % (int(self.floating_h)))
|
||||
config.set("notification", "bg_col", json.dumps(self.bg_col))
|
||||
config.set("notification", "fg_col", json.dumps(self.fg_col))
|
||||
config.set("notification", "text_time", "%s" % (int(self.text_time)))
|
||||
config.set("notification", "show_icon", "%s" %
|
||||
(int(self.show_icon)))
|
||||
config.set("notification", "rev", "%s" %
|
||||
(int(self.reverse_order)))
|
||||
config.set("notification", "limit_width", "%d" %
|
||||
(int(self.limit_width)))
|
||||
config.set("notification", "icon_left", "%d" % (int(self.icon_left)))
|
||||
config.set("notification", "icon_padding", "%d" %
|
||||
(int(self.icon_padding)))
|
||||
config.set("notification", "icon_size", "%d" % (int(self.icon_size)))
|
||||
config.set("notification", "padding", "%d" % (int(self.padding)))
|
||||
config.set("notification", "border_radius", "%d" %
|
||||
(int(self.border_radius)))
|
||||
|
||||
if self.font:
|
||||
config.set("notification", "font", self.font)
|
||||
|
||||
with open(self.config_file, 'w') as file:
|
||||
config.write(file)
|
||||
|
||||
def create_gui(self):
|
||||
"""
|
||||
Prepare the gui
|
||||
"""
|
||||
box = Gtk.Grid()
|
||||
|
||||
# Enabled
|
||||
enabled_label = Gtk.Label.new("Enable")
|
||||
enabled = Gtk.CheckButton.new()
|
||||
enabled.set_active(self.enabled)
|
||||
enabled.connect("toggled", self.change_enabled)
|
||||
|
||||
# Enabled
|
||||
testing_label = Gtk.Label.new("Show test content")
|
||||
testing = Gtk.CheckButton.new()
|
||||
testing.connect("toggled", self.change_testing)
|
||||
|
||||
# Order
|
||||
reverse_label = Gtk.Label.new("Reverse Order")
|
||||
reverse = Gtk.CheckButton.new()
|
||||
reverse.set_active(self.reverse_order)
|
||||
reverse.connect("toggled", self.change_reverse_order)
|
||||
|
||||
# Popup timer
|
||||
text_time_label = Gtk.Label.new("Popup timer")
|
||||
text_time_adjustment = Gtk.Adjustment.new(
|
||||
self.text_time, 8, 9000, 1, 1, 8)
|
||||
text_time = Gtk.SpinButton.new(text_time_adjustment, 0, 0)
|
||||
text_time.connect("value-changed", self.change_text_time)
|
||||
|
||||
# Limit width
|
||||
limit_width_label = Gtk.Label.new("Limit popup width")
|
||||
limit_width_adjustment = Gtk.Adjustment.new(
|
||||
self.limit_width, 100, 9000, 1, 1, 8)
|
||||
limit_width = Gtk.SpinButton.new(limit_width_adjustment, 0, 0)
|
||||
limit_width.connect("value-changed", self.change_limit_width)
|
||||
|
||||
# Font chooser
|
||||
font_label = Gtk.Label.new("Font")
|
||||
font = Gtk.FontButton()
|
||||
if self.font:
|
||||
font.set_font(self.font)
|
||||
font.connect("font-set", self.change_font)
|
||||
|
||||
# Icon alignment
|
||||
align_icon_label = Gtk.Label.new("Icon position")
|
||||
align_icon_store = Gtk.ListStore(str)
|
||||
align_icon_store.append(["Left"])
|
||||
align_icon_store.append(["Right"])
|
||||
align_icon = Gtk.ComboBox.new_with_model(align_icon_store)
|
||||
align_icon.set_active(not self.icon_left)
|
||||
align_icon.connect("changed", self.change_icon_left)
|
||||
renderer_text = Gtk.CellRendererText()
|
||||
align_icon.pack_start(renderer_text, True)
|
||||
align_icon.add_attribute(renderer_text, "text", 0)
|
||||
|
||||
# Colours
|
||||
bg_col_label = Gtk.Label.new("Background colour")
|
||||
bg_col = Gtk.ColorButton.new_with_rgba(
|
||||
Gdk.RGBA(self.bg_col[0], self.bg_col[1], self.bg_col[2], self.bg_col[3]))
|
||||
fg_col_label = Gtk.Label.new("Text colour")
|
||||
fg_col = Gtk.ColorButton.new_with_rgba(
|
||||
Gdk.RGBA(self.fg_col[0], self.fg_col[1], self.fg_col[2], self.fg_col[3]))
|
||||
bg_col.set_use_alpha(True)
|
||||
fg_col.set_use_alpha(True)
|
||||
bg_col.connect("color-set", self.change_bg)
|
||||
fg_col.connect("color-set", self.change_fg)
|
||||
|
||||
# Monitor & Alignment
|
||||
align_label = Gtk.Label.new("Overlay Location")
|
||||
|
||||
align_type_box = Gtk.HBox()
|
||||
align_type_edge = Gtk.RadioButton.new_with_label(
|
||||
None, "Anchor to edge")
|
||||
align_type_floating = Gtk.RadioButton.new_with_label_from_widget(
|
||||
align_type_edge, "Floating")
|
||||
if self.floating:
|
||||
align_type_floating.set_active(True)
|
||||
align_type_box.add(align_type_edge)
|
||||
align_type_box.add(align_type_floating)
|
||||
|
||||
monitor_store = Gtk.ListStore(str)
|
||||
display = Gdk.Display.get_default()
|
||||
if "get_n_monitors" in dir(display):
|
||||
for i in range(0, display.get_n_monitors()):
|
||||
monitor_store.append([display.get_monitor(i).get_model()])
|
||||
monitor = Gtk.ComboBox.new_with_model(monitor_store)
|
||||
monitor.set_active(self.get_monitor_index(self.monitor))
|
||||
monitor.connect("changed", self.change_monitor)
|
||||
renderer_text = Gtk.CellRendererText()
|
||||
monitor.pack_start(renderer_text, True)
|
||||
monitor.add_attribute(renderer_text, "text", 0)
|
||||
|
||||
align_x_store = Gtk.ListStore(str)
|
||||
align_x_store.append(["Left"])
|
||||
align_x_store.append(["Right"])
|
||||
align_x = Gtk.ComboBox.new_with_model(align_x_store)
|
||||
align_x.set_active(True if self.align_x else False)
|
||||
align_x.connect("changed", self.change_align_x)
|
||||
renderer_text = Gtk.CellRendererText()
|
||||
align_x.pack_start(renderer_text, True)
|
||||
align_x.add_attribute(renderer_text, "text", 0)
|
||||
|
||||
align_y_store = Gtk.ListStore(str)
|
||||
align_y_store.append(["Top"])
|
||||
align_y_store.append(["Middle"])
|
||||
align_y_store.append(["Bottom"])
|
||||
align_y = Gtk.ComboBox.new_with_model(align_y_store)
|
||||
align_y.set_active(self.align_y)
|
||||
align_y.connect("changed", self.change_align_y)
|
||||
renderer_text = Gtk.CellRendererText()
|
||||
align_y.pack_start(renderer_text, True)
|
||||
align_y.add_attribute(renderer_text, "text", 0)
|
||||
|
||||
align_placement_button = Gtk.Button.new_with_label("Place Window")
|
||||
|
||||
align_type_edge.connect("toggled", self.change_align_type_edge)
|
||||
align_type_floating.connect("toggled", self.change_align_type_floating)
|
||||
align_placement_button.connect("pressed", self.change_placement)
|
||||
|
||||
# Show Icons
|
||||
show_icon_label = Gtk.Label.new("Show Icon")
|
||||
show_icon = Gtk.CheckButton.new()
|
||||
show_icon.set_active(self.show_icon)
|
||||
show_icon.connect("toggled", self.change_show_icon)
|
||||
|
||||
# Icon Padding
|
||||
icon_padding_label = Gtk.Label.new("Icon padding")
|
||||
icon_padding_adjustment = Gtk.Adjustment.new(
|
||||
self.icon_padding, 0, 150, 1, 1, 8)
|
||||
icon_padding = Gtk.SpinButton.new(icon_padding_adjustment, 0, 0)
|
||||
icon_padding.connect("value-changed", self.change_icon_pad)
|
||||
|
||||
# Icon Size
|
||||
icon_size_label = Gtk.Label.new("Icon size")
|
||||
icon_size_adjustment = Gtk.Adjustment.new(
|
||||
self.icon_size, 0, 128, 1, 1, 8)
|
||||
icon_size = Gtk.SpinButton.new(icon_size_adjustment, 0, 0)
|
||||
icon_size.connect("value-changed", self.change_icon_size)
|
||||
|
||||
# Padding
|
||||
padding_label = Gtk.Label.new("Notification padding")
|
||||
padding_adjustment = Gtk.Adjustment.new(
|
||||
self.padding, 0, 150, 1, 1, 8)
|
||||
padding = Gtk.SpinButton.new(padding_adjustment, 0, 0)
|
||||
padding.connect("value-changed", self.change_padding)
|
||||
|
||||
# Border Radius
|
||||
border_radius_label = Gtk.Label.new("Border radius")
|
||||
border_radius_adjustment = Gtk.Adjustment.new(
|
||||
self.border_radius, 0, 50, 1, 1, 8)
|
||||
border_radius = Gtk.SpinButton.new(border_radius_adjustment, 0, 0)
|
||||
border_radius.connect(
|
||||
"value-changed", self.change_border_radius)
|
||||
|
||||
self.align_x_widget = align_x
|
||||
self.align_y_widget = align_y
|
||||
self.align_monitor_widget = monitor
|
||||
self.align_placement_widget = align_placement_button
|
||||
self.text_time_widget = text_time
|
||||
self.text_time_label_widget = text_time_label
|
||||
|
||||
box.attach(enabled_label, 0, 0, 1, 1)
|
||||
box.attach(enabled, 1, 0, 1, 1)
|
||||
box.attach(reverse_label, 0, 1, 1, 1)
|
||||
box.attach(reverse, 1, 1, 1, 1)
|
||||
box.attach(text_time_label, 0, 3, 1, 1)
|
||||
box.attach(text_time, 1, 3, 1, 1)
|
||||
box.attach(limit_width_label, 0, 4, 1, 1)
|
||||
box.attach(limit_width, 1, 4, 1, 1)
|
||||
|
||||
box.attach(font_label, 0, 6, 1, 1)
|
||||
box.attach(font, 1, 6, 1, 1)
|
||||
box.attach(fg_col_label, 0, 7, 1, 1)
|
||||
box.attach(fg_col, 1, 7, 1, 1)
|
||||
box.attach(bg_col_label, 0, 8, 1, 1)
|
||||
box.attach(bg_col, 1, 8, 1, 1)
|
||||
box.attach(align_label, 0, 9, 1, 5)
|
||||
#box.attach(align_type_box, 1, 8, 1, 1)
|
||||
box.attach(monitor, 1, 10, 1, 1)
|
||||
box.attach(align_x, 1, 11, 1, 1)
|
||||
box.attach(align_y, 1, 12, 1, 1)
|
||||
box.attach(align_placement_button, 1, 13, 1, 1)
|
||||
box.attach(show_icon_label, 0, 14, 1, 1)
|
||||
box.attach(show_icon, 1, 14, 1, 1)
|
||||
box.attach(align_icon_label, 0, 15, 1, 1)
|
||||
box.attach(align_icon, 1, 15, 1, 1)
|
||||
box.attach(icon_padding_label, 0, 16, 1, 1)
|
||||
box.attach(icon_padding, 1, 16, 1, 1)
|
||||
box.attach(icon_size_label, 0, 17, 1, 1)
|
||||
box.attach(icon_size, 1, 17, 1, 1)
|
||||
box.attach(padding_label, 0, 18, 1, 1)
|
||||
box.attach(padding, 1, 18, 1, 1)
|
||||
|
||||
box.attach(testing_label, 0, 20, 1, 1)
|
||||
box.attach(testing, 1, 20, 1, 1)
|
||||
|
||||
self.add(box)
|
||||
|
||||
def change_padding(self, button):
|
||||
"""
|
||||
Padding between notifications changed
|
||||
"""
|
||||
self.overlay.set_padding(button.get_value())
|
||||
self.padding = button.get_value()
|
||||
|
||||
self.save_config()
|
||||
|
||||
def change_border_radius(self, button):
|
||||
"""
|
||||
Border radius changed
|
||||
"""
|
||||
self.overlay.set_border_radius(button.get_value())
|
||||
self.padding = button.get_value()
|
||||
|
||||
self.save_config()
|
||||
|
||||
def change_icon_size(self, button):
|
||||
"""
|
||||
Icon size changed
|
||||
"""
|
||||
self.overlay.set_icon_size(button.get_value())
|
||||
self.icon_size = button.get_value()
|
||||
|
||||
self.save_config()
|
||||
|
||||
def change_icon_pad(self, button):
|
||||
"""
|
||||
Icon padding changed
|
||||
"""
|
||||
self.overlay.set_icon_pad(button.get_value())
|
||||
self.icon_pad = button.get_value()
|
||||
|
||||
self.save_config()
|
||||
|
||||
def change_icon_left(self, button):
|
||||
"""
|
||||
Icon alignment changed
|
||||
"""
|
||||
self.overlay.set_icon_left(button.get_active() != 1)
|
||||
self.icon_left = (button.get_active() != 1)
|
||||
|
||||
self.save_config()
|
||||
|
||||
def change_font(self, button):
|
||||
"""
|
||||
Font settings changed
|
||||
"""
|
||||
font = button.get_font()
|
||||
self.overlay.set_font(font)
|
||||
|
||||
self.font = font
|
||||
self.save_config()
|
||||
|
||||
def change_text_time(self, button):
|
||||
"""
|
||||
Popup style setting changed
|
||||
"""
|
||||
self.overlay.set_text_time(button.get_value())
|
||||
|
||||
self.text_time = button.get_value()
|
||||
self.save_config()
|
||||
|
||||
def change_limit_width(self, button):
|
||||
"""
|
||||
Popup width limiter
|
||||
"""
|
||||
self.overlay.set_limit_width(button.get_value())
|
||||
self.limit_width = button.get_value()
|
||||
self.save_config()
|
||||
|
||||
def change_bg(self, button):
|
||||
"""
|
||||
Background colour changed
|
||||
"""
|
||||
colour = button.get_rgba()
|
||||
colour = [colour.red, colour.green, colour.blue, colour.alpha]
|
||||
self.overlay.set_bg(colour)
|
||||
|
||||
self.bg_col = colour
|
||||
self.save_config()
|
||||
|
||||
def change_fg(self, button):
|
||||
"""
|
||||
Foreground colour changed
|
||||
"""
|
||||
colour = button.get_rgba()
|
||||
colour = [colour.red, colour.green, colour.blue, colour.alpha]
|
||||
self.overlay.set_fg(colour)
|
||||
|
||||
self.fg_col = colour
|
||||
self.save_config()
|
||||
|
||||
def change_show_icon(self, button):
|
||||
"""
|
||||
Icon setting changed
|
||||
"""
|
||||
self.overlay.set_show_icon(button.get_active())
|
||||
|
||||
self.show_icon = button.get_active()
|
||||
self.save_config()
|
||||
|
||||
def change_reverse_order(self, button):
|
||||
"""
|
||||
Reverse Order changed
|
||||
"""
|
||||
self.overlay.set_reverse_order(button.get_active())
|
||||
|
||||
self.reverse_order = button.get_active()
|
||||
self.save_config()
|
||||
|
||||
def change_testing(self, button):
|
||||
self.overlay.set_testing(button.get_active())
|
||||
|
||||
def change_enabled(self, button):
|
||||
"""
|
||||
Overlay active state toggled
|
||||
"""
|
||||
self.overlay.set_enabled(button.get_active())
|
||||
self.enabled = button.get_active()
|
||||
self.discover.set_dbus_notifications(self.enabled)
|
||||
self.save_config()
|
||||
|
|
@ -318,6 +318,7 @@ class OverlayWindow(Gtk.Window):
|
|||
self.enabled = enabled
|
||||
if enabled and not self.hidden and not self.piggyback_parent:
|
||||
self.show_all()
|
||||
self.set_untouchable()
|
||||
else:
|
||||
self.hide()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from .voice_settings import VoiceSettingsWindow
|
|||
from .text_settings import TextSettingsWindow
|
||||
from .general_settings import GeneralSettingsWindow
|
||||
from .about_settings import AboutSettingsWindow
|
||||
from .notification_settings import NotificationSettingsWindow
|
||||
gi.require_version("Gtk", "3.0")
|
||||
# pylint: disable=wrong-import-position,wrong-import-order
|
||||
from gi.repository import Gtk # nopep8
|
||||
|
|
@ -33,6 +34,7 @@ class MainSettingsWindow(Gtk.Window):
|
|||
self.discover = discover
|
||||
self.text_overlay = discover.text_overlay
|
||||
self.voice_overlay = discover.voice_overlay
|
||||
self.notification_overlay = discover.notification_overlay
|
||||
self.set_title("Discover Overlay Configuration")
|
||||
self.set_icon_name("discover-overlay")
|
||||
self.set_default_size(280, 180)
|
||||
|
|
@ -56,10 +58,15 @@ class MainSettingsWindow(Gtk.Window):
|
|||
|
||||
self.text_settings = TextSettingsWindow(self.text_overlay, discover)
|
||||
text_label = Gtk.Label.new("Text")
|
||||
|
||||
notebook.append_page(self.text_settings)
|
||||
notebook.set_tab_label(self.text_settings, text_label)
|
||||
|
||||
self.notification_settings = NotificationSettingsWindow(
|
||||
self.notification_overlay, discover)
|
||||
notification_label = Gtk.Label.new("Notifications")
|
||||
notebook.append_page(self.notification_settings)
|
||||
notebook.set_tab_label(self.notification_settings, notification_label)
|
||||
|
||||
self.core_settings = GeneralSettingsWindow(self.discover)
|
||||
core_label = Gtk.Label.new("Core")
|
||||
notebook.append_page(self.core_settings)
|
||||
|
|
@ -84,6 +91,7 @@ class MainSettingsWindow(Gtk.Window):
|
|||
self.about_settings.present_settings()
|
||||
self.voice_settings.present_settings()
|
||||
self.text_settings.present_settings()
|
||||
self.notification_settings.present_settings()
|
||||
self.core_settings.present_settings()
|
||||
self.notebook.show()
|
||||
self.show()
|
||||
|
|
|
|||
|
|
@ -168,19 +168,21 @@ class TextOverlayWindow(OverlayWindow):
|
|||
self.needsredraw = True
|
||||
logging.info("recv_attach redraw")
|
||||
|
||||
def overlay_draw(self, _w, context, data=None):
|
||||
def overlay_draw(self, w, context, data=None):
|
||||
"""
|
||||
Draw the overlay
|
||||
"""
|
||||
if self.piggyback:
|
||||
self.piggyback.overlay_draw(w, context, data)
|
||||
if not self.enabled:
|
||||
return
|
||||
self.context = context
|
||||
context.set_antialias(cairo.ANTIALIAS_GOOD)
|
||||
(width, height) = self.get_size()
|
||||
# Make background transparent
|
||||
context.set_source_rgba(0.0, 0.0, 0.0, 0.0)
|
||||
context.set_operator(cairo.OPERATOR_SOURCE)
|
||||
context.paint()
|
||||
if not self.piggyback_parent:
|
||||
context.set_antialias(cairo.ANTIALIAS_GOOD)
|
||||
context.set_source_rgba(0.0, 0.0, 0.0, 0.0)
|
||||
context.set_operator(cairo.OPERATOR_SOURCE)
|
||||
context.paint()
|
||||
context.save()
|
||||
if self.is_wayland or self.piggyback_parent or self.discover.steamos:
|
||||
# Special case!
|
||||
|
|
|
|||
|
|
@ -357,8 +357,7 @@ class VoiceOverlayWindow(OverlayWindow):
|
|||
self.def_avatar = pix
|
||||
else:
|
||||
self.avatars[identifier] = pix
|
||||
if self.context:
|
||||
self.needsredraw = True
|
||||
self.needsredraw = True
|
||||
|
||||
def delete_avatar(self, identifier):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue