- Changed all one or two character long variable names to be more clear what they are

- Limited line lengths
- Fixed #95
This commit is contained in:
trigg 2020-10-20 14:07:14 +00:00
parent 3dd4fdb4ee
commit 719dc6c19e
11 changed files with 497 additions and 447 deletions

View file

@ -21,16 +21,12 @@ from gi.repository import Gtk, Gdk
class DraggableWindow(Gtk.Window):
"""An X11 window which can be moved and resized"""
def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None):
def __init__(self, pos_x=0, pos_y=0, width=300, height=300, message="Message", settings=None):
Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP)
if w < 100:
w = 100
if h < 100:
h = 100
self.x = x
self.y = y
self.w = w
self.h = h
self.pos_x = pos_x
self.pos_y = pos_y
self.width = max(100, width)
self.height = max(100, height)
self.settings = settings
self.message = message
self.set_size_request(50, 50)
@ -60,48 +56,51 @@ class DraggableWindow(Gtk.Window):
self.show_all()
def force_location(self):
"""Move the window to previously given co-ords. Also double check sanity on layer & decorations"""
"""
Move the window to previously given co-ords.
Also double check sanity on layer & decorations
"""
self.set_decorated(False)
self.set_keep_above(True)
self.move(self.x, self.y)
self.resize(self.w, self.h)
self.move(self.pos_x, self.pos_y)
self.resize(self.width, self.height)
def drag(self, _w, event):
"""Called by GTK while mouse is moving over window. Used to resize and move"""
if event.state & Gdk.ModifierType.BUTTON1_MASK:
if self.drag_type == 1:
# Center is move
self.x = event.x_root - self.drag_x
self.y = event.y_root - self.drag_y
self.pos_x = event.x_root - self.drag_x
self.pos_y = event.y_root - self.drag_y
self.force_location()
elif self.drag_type == 2:
# Right edge
self.w += event.x - self.drag_x
self.width += event.x - self.drag_x
self.drag_x = event.x
self.force_location()
elif self.drag_type == 3:
# Bottom edge
self.h += event.y - self.drag_y
self.height += event.y - self.drag_y
self.drag_y = event.y
self.force_location()
else:
# Bottom Right
self.w += event.x - self.drag_x
self.h += event.y - self.drag_y
self.width += event.x - self.drag_x
self.height += event.y - self.drag_y
self.drag_x = event.x
self.drag_y = event.y
self.force_location()
def button_press(self, w, event):
def button_press(self, _widget, event):
"""Called when a mouse button is pressed on this window"""
(w, h) = self.get_size()
(width, height) = self.get_size()
if not self.drag_type:
self.drag_type = 1
# Where in the window did we press?
if event.y > h - 32:
if event.y > height - 32:
self.drag_type += 2
if event.x > w - 32:
if event.x > width - 32:
self.drag_type += 1
self.drag_x = event.x
self.drag_y = event.y
@ -118,24 +117,26 @@ class DraggableWindow(Gtk.Window):
context.paint()
context.set_operator(cairo.OPERATOR_OVER)
# Get size of window
(sw, sh) = self.get_size()
(window_width, window_height) = self.get_size()
# Draw text
context.set_source_rgba(0.0, 0.0, 0.0, 1.0)
_xb, _yb, w, h, _dx, _dy = context.text_extents(self.message)
context.move_to(sw / 2 - w / 2, sh / 2 - h / 2)
_xb, _yb, text_width, text_height, _dx, _dy = context.text_extents(
self.message)
context.move_to(window_width / 2 - text_width / 2,
window_height / 2 - text_height / 2)
context.show_text(self.message)
# Draw resizing edges
context.set_source_rgba(0.0, 0.0, 1.0, 0.5)
context.rectangle(sw - 32, 0, 32, sh)
context.rectangle(window_width - 32, 0, 32, window_height)
context.fill()
context.rectangle(0, sh - 32, sw, 32)
context.rectangle(0, window_height - 32, window_width, 32)
context.fill()
def get_coords(self):
"""Return window position and size"""
(x, y) = self.get_position()
(w, h) = self.get_size()
return (x, y, w, h)
(pos_x, pos_y) = self.get_position()
(width, height) = self.get_size()
return (pos_x, pos_y, width, height)

View file

@ -25,16 +25,12 @@ except ImportError:
class DraggableWindowWayland(Gtk.Window):
"""A Wayland full-screen window which can be moved and resized"""
def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None):
def __init__(self, pos_x=0, pos_y=0, width=300, height=300, message="Message", settings=None):
Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL)
if w < 100:
w = 100
if h < 100:
h = 100
self.x = x
self.y = y
self.w = w
self.h = h
self.pos_x = pos_x
self.pos_y = pos_y
self.width = max(100, width)
self.height = max(100, height)
self.settings = settings
self.message = message
self.set_size_request(50, 50)
@ -63,14 +59,10 @@ class DraggableWindowWayland(Gtk.Window):
def force_location(self):
"""Move the window to previously given co-ords. In wayland just clip to current screen"""
(size_x, size_y) = self.get_size()
if self.x < 0:
self.x = 0
if self.y < 0:
self.y = 0
if self.x + self.w > size_x:
self.x = size_x - self.w
if self.y + self.h > size_y:
self.y = size_y - self.h
self.pos_x = max(0, self.pos_x)
self.pos_x = min(size_x - self.width, self.pos_x)
self.pos_y = max(0, self.pos_y)
self.pos_y = min(size_y - self.height, self.pos_y)
self.queue_draw()
def drag(self, _w, event):
@ -78,43 +70,43 @@ class DraggableWindowWayland(Gtk.Window):
if event.state & Gdk.ModifierType.BUTTON1_MASK:
if self.drag_type == 1:
# Center is move
self.x += event.x - self.drag_x
self.y += event.y - self.drag_y
self.pos_x += event.x - self.drag_x
self.pos_y += event.y - self.drag_y
self.drag_x = event.x
self.drag_y = event.y
self.force_location()
elif self.drag_type == 2:
# Right edge
self.w += event.x - self.drag_x
self.width += event.x - self.drag_x
self.drag_x = event.x
self.force_location()
elif self.drag_type == 3:
# Bottom edge
self.h += event.y - self.drag_y
self.height += event.y - self.drag_y
self.drag_y = event.y
self.force_location()
else:
# Bottom Right
self.w += event.x - self.drag_x
self.h += event.y - self.drag_y
self.width += event.x - self.drag_x
self.height += event.y - self.drag_y
self.drag_x = event.x
self.drag_y = event.y
self.force_location()
def button_press(self, _w, event):
"""Called when a mouse button is pressed on this window"""
px = event.x - self.x
py = event.y - self.y
press_x = event.x - self.pos_x
press_y = event.y - self.pos_y
if not self.drag_type:
self.drag_type = 1
# Where in the window did we press?
if px < 20 and py < 20:
if press_x < 20 and press_y < 20:
self.settings.change_placement(None)
if py > self.h - 32:
if press_y > self.height - 32:
self.drag_type += 2
if px > self.w - 32:
if press_x > self.width - 32:
self.drag_type += 1
self.drag_x = event.x
self.drag_y = event.y
@ -124,10 +116,14 @@ class DraggableWindowWayland(Gtk.Window):
self.drag_type = None
def dodraw(self, _widget, context):
"""Draw our window. For wayland we're secretly a fullscreen app and need to draw only a single rectangle of the overlay"""
context.translate(self.x, self.y)
"""
Draw our window. For wayland we're secretly a
fullscreen app and need to draw only a single
rectangle of the overlay
"""
context.translate(self.pos_x, self.pos_y)
context.save()
context.rectangle(0, 0, self.w, self.h)
context.rectangle(0, 0, self.width, self.height)
context.clip()
context.set_source_rgba(1.0, 1.0, 0.0, 0.7)
@ -139,15 +135,16 @@ class DraggableWindowWayland(Gtk.Window):
# Draw text
context.set_source_rgba(0.0, 0.0, 0.0, 1.0)
_xb, _yb, width, height, _dx, _dy = context.text_extents(self.message)
context.move_to(self.w / 2 - width / 2, self.h / 2 - height / 2)
context.move_to(self.width / 2 - width / 2,
self.height / 2 - height / 2)
context.show_text(self.message)
# Draw resizing edges
context.set_source_rgba(0.0, 0.0, 1.0, 0.5)
context.rectangle(self.w - 32, 0, 32, self.h)
context.rectangle(self.width - 32, 0, 32, self.height)
context.fill()
context.rectangle(0, self.h - 32, self.w, 32)
context.rectangle(0, self.height - 32, self.width, 32)
context.fill()
# Draw Done!
@ -158,4 +155,4 @@ class DraggableWindowWayland(Gtk.Window):
def get_coords(self):
"""Return the position and size of the window"""
return (self.x, self.y, self.w, self.h)
return (self.pos_x, self.pos_y, self.width, self.height)

View file

@ -16,7 +16,7 @@ import gi
from .settings import SettingsWindow
from .autostart import Autostart
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Gtk
@ -28,19 +28,18 @@ class GeneralSettingsWindow(SettingsWindow):
self.overlay = overlay
self.overlay2 = overlay2
self.xshape = None
self.autostart = None
self.set_size_request(400, 200)
self.connect("destroy", self.close_window)
self.connect("delete-event", self.close_window)
self.init_config()
self.a = Autostart("discover_overlay")
self.autostart_helper = Autostart("discover_overlay")
self.placement_window = None
self.create_gui()
def read_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
self.xshape = config.getboolean("general", "xshape", fallback=False)
# Pass all of our config over to the overlay
@ -49,13 +48,13 @@ class GeneralSettingsWindow(SettingsWindow):
def save_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
if not config.has_section("general"):
config.add_section("general")
config.set("general", "xshape", "%d" % (int(self.xshape)))
with open(self.configFile, 'w') as file:
with open(self.config_file, 'w') as file:
config.write(file)
def create_gui(self):
@ -64,7 +63,7 @@ class GeneralSettingsWindow(SettingsWindow):
# Auto start
autostart_label = Gtk.Label.new("Autostart on boot")
autostart = Gtk.CheckButton.new()
autostart.set_active(self.a.is_auto())
autostart.set_active(self.autostart_helper.is_auto())
autostart.connect("toggled", self.change_autostart)
# Force XShape
@ -81,8 +80,8 @@ class GeneralSettingsWindow(SettingsWindow):
self.add(box)
def change_autostart(self, button):
self.autostart = button.get_active()
self.a.set_autostart(self.autostart)
autostart = button.get_active()
self.autostart_helper.set_autostart(autostart)
def change_xshape(self, button):
self.overlay.set_force_xshape(button.get_active())

View file

@ -28,7 +28,7 @@ class ImageGetter():
def __init__(self, func, url, identifier, size):
self.func = func
self.id = identifier
self.identifier = identifier
self.url = url
self.size = size
@ -46,7 +46,7 @@ class ImageGetter():
pixbuf = pixbuf.scale_simple(self.size, self.size,
GdkPixbuf.InterpType.BILINEAR)
self.func(self.id, pixbuf)
self.func(self.identifier, pixbuf)
except urllib.error.URLError as exception:
logging.error(
"Could not access : %s", self.url)
@ -58,20 +58,24 @@ class SurfaceGetter():
def __init__(self, func, url, identifier, size):
self.func = func
self.id = identifier
self.identifier = identifier
self.url = url
self.size = size
def get_url(self):
"""Downloads and decodes"""
try:
resp = requests.get(self.url, stream=True, headers={
'Referer': 'https://streamkit.discord.com/overlay/voice', 'User-Agent': 'Mozilla/5.0'})
resp = requests.get(
self.url, stream=True, headers={
'Referer': 'https://streamkit.discord.com/overlay/voice',
'User-Agent': 'Mozilla/5.0'
}
)
raw = resp.raw
im = Image.open(raw)
surf = self.from_pil(im)
image = Image.open(raw)
surface = self.from_pil(image)
self.func(self.id, surf)
self.func(self.identifier, surface)
except requests.HTTPError:
logging.error("Unable to open %s", self.url)
except requests.TooManyRedirects:
@ -85,84 +89,86 @@ class SurfaceGetter():
except TypeError:
logging.error("Unable to read %s", self.url)
def from_pil(self, im, alpha=1.0):
def from_pil(self, image, alpha=1.0):
"""
:param im: Pillow Image
:param alpha: 0..1 alpha to add to non-alpha images
:param format: Pixel format for output surface
"""
if 'A' not in im.getbands():
im.putalpha(int(alpha * 256.))
arr = bytearray(im.tobytes('raw', 'BGRa'))
if 'A' not in image.getbands():
image.putalpha(int(alpha * 256.))
arr = bytearray(image.tobytes('raw', 'BGRa'))
surface = cairo.ImageSurface.create_for_data(
arr, cairo.FORMAT_ARGB32, im.width, im.height)
arr, cairo.FORMAT_ARGB32, image.width, image.height)
return surface
def get_image(func, identifier, ava, size):
"""Download to GDK Pixmap"""
image_getter = ImageGetter(func, identifier, ava, size)
t = threading.Thread(target=image_getter.get_url, args=())
t.start()
thread = threading.Thread(target=image_getter.get_url, args=())
thread.start()
def get_surface(func, identifier, ava, size):
"""Download to cairo surface"""
image_getter = SurfaceGetter(func, identifier, ava, size)
t = threading.Thread(target=image_getter.get_url, args=())
t.start()
thread = threading.Thread(target=image_getter.get_url, args=())
thread.start()
def get_aspected_size(img, w, h, anchor=0, hanchor=0):
def get_aspected_size(img, width, height, anchor=0, hanchor=0):
"""Get dimensions of image keeping current aspect ratio"""
px = img.get_width()
py = img.get_height()
if py < 1 or h < 1:
pic_width = img.get_width()
pic_height = img.get_height()
if pic_height < 1 or height < 1:
return (0, 0, 0, 0)
img_aspect = px / py
rect_aspect = w / h
img_aspect = pic_width / pic_height
rect_aspect = width / height
y = 0
x = 0
offset_y = 0
offset_x = 0
if img_aspect > rect_aspect:
oh = h
h = w / img_aspect
old_height = height
height = width / img_aspect
if anchor == 0:
y = y + (oh - h)
offset_y = offset_y + (old_height - height)
if anchor == 1:
y = y + ((oh - h) / 2)
offset_y = offset_y + ((old_height - height) / 2)
elif img_aspect < rect_aspect:
ow = w
w = h * img_aspect
old_width = width
width = height * img_aspect
if hanchor == 2:
x = x + (ow - w)
offset_x = offset_x + (old_width - width)
if hanchor == 1:
x = x + ((ow - w) / 2)
return (x, y, w, h)
offset_x = offset_x + ((old_width - width) / 2)
return (offset_x, offset_y, width, height)
def draw_img_to_rect(img, ctx, x, y, w, h, path=False, aspect=False, anchor=0, hanchor=0):
def draw_img_to_rect(img, ctx,
pos_x, pos_y,
width, height,
path=False, aspect=False,
anchor=0, hanchor=0):
"""Draw cairo surface onto context"""
# Path - only add the path do not fill : True/False
# Aspect - keep aspect ratio : True/False
# Anchor - with aspect : 0=left 1=middle 2=right
# HAnchor - with apect : 0=bottom 1=middle 2=top
ctx.save()
px = img.get_width()
py = img.get_height()
x_off = 0
y_off = 0
offset_x = 0
offset_y = 0
if aspect:
(x_off, y_off, w, h) = get_aspected_size(
img, w, h, anchor=anchor, hanchor=hanchor)
(offset_x, offset_y, width, height) = get_aspected_size(
img, width, height, anchor=anchor, hanchor=hanchor)
ctx.translate(x + x_off, y + y_off)
ctx.scale(w, h)
ctx.scale(1 / px, 1 / py)
ctx.translate(pos_x + offset_x, pos_y + offset_y)
ctx.scale(width, height)
ctx.scale(1 / img.get_width(), 1 / img.get_height())
ctx.set_source_surface(img, 0, 0)
ctx.rectangle(0, 0, px, py)
ctx.rectangle(0, 0, img.get_width(), img.get_height())
if not path:
ctx.fill()
ctx.restore()
return (w, h)
return (width, height)

View file

@ -10,13 +10,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""Overlay parent class. Helpful if we need more overlay types without copy-and-pasting too much code"""
"""
Overlay parent class. Helpful if we need more overlay
types without copy-and-pasting too much code
"""
import sys
import logging
import gi
import cairo
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Gtk, Gdk
try:
from gi.repository import GtkLayerShell
@ -25,7 +28,10 @@ except ImportError:
class OverlayWindow(Gtk.Window):
"""Overlay parent class. Helpful if we need more overlay types without copy-and-pasting too much code"""
"""
Overlay parent class. Helpful if we need more overlay
types without copy-and-pasting too much code
"""
def detect_type(self):
window = Gtk.Window()
@ -43,10 +49,10 @@ class OverlayWindow(Gtk.Window):
self.compositing = False
self.text_font = None
self.text_size = None
self.x = None
self.y = None
self.w = None
self.h = None
self.pos_x = None
self.pos_y = None
self.width = None
self.height = None
self.set_size_request(50, 50)
self.connect('draw', self.overlay_draw)
@ -97,24 +103,23 @@ class OverlayWindow(Gtk.Window):
self.text_size = size
self.redraw()
def set_floating(self, floating, x, y, w, h):
def set_floating(self, floating, pos_x, pos_y, width, height):
self.floating = floating
self.x = x
self.y = y
self.w = w
self.h = h
self.pos_x = pos_x
self.pos_y = pos_y
self.width = width
self.height = height
self.force_location()
def set_untouchable(self):
(w, h) = self.get_size()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
(width, height) = self.get_size()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
surface_ctx = cairo.Context(surface)
surface_ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0)
surface_ctx.set_operator(cairo.OPERATOR_SOURCE)
surface_ctx.paint()
reg = Gdk.cairo_region_create_from_surface(surface)
self.input_shape_combine_region(reg)
# self.shape_combine_region(reg)
def unset_shape(self):
self.get_window().shape_combine_region(None, 0, 0)
@ -129,43 +134,38 @@ class OverlayWindow(Gtk.Window):
geometry = monitor.get_geometry()
scale_factor = monitor.get_scale_factor()
if not self.floating:
w = scale_factor * geometry.width
h = scale_factor * geometry.height
x = geometry.x
y = geometry.y
self.resize(w, h)
self.move(x, y)
width = scale_factor * geometry.width
height = scale_factor * geometry.height
pos_x = geometry.x
pos_y = geometry.y
self.resize(width, height)
self.move(pos_x, pos_y)
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
self.move(self.pos_x, self.pos_y)
self.resize(self.width, self.height)
else:
if not self.floating:
screen = display.get_default_screen()
w = screen.width()
h = screen.height()
x = 0
y = 0
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
if self.floating:
self.move(self.pos_x, self.pos_y)
self.resize(self.width, self.height)
if not self.floating:
(w, h) = self.get_size()
self.w = w
self.h = h
(width, height) = self.get_size()
self.width = width
self.height = height
self.redraw()
def redraw(self):
gdkwin = self.get_window()
if not self.floating:
(w, h) = self.get_size()
self.w = w
self.h = h
(width, height) = self.get_size()
self.width = width
self.height = height
if gdkwin:
if not self.compositing or self.force_xshape:
(w, h) = self.get_size()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
(width, height) = self.get_size()
surface = cairo.ImageSurface(
cairo.FORMAT_ARGB32, width, height)
surface_ctx = cairo.Context(surface)
self.overlay_draw(None, surface_ctx)
reg = Gdk.cairo_region_create_from_surface(surface)
@ -182,18 +182,18 @@ class OverlayWindow(Gtk.Window):
self.force_location()
self.redraw()
def set_align_x(self, b):
self.align_right = b
def set_align_x(self, align_right):
self.align_right = align_right
self.force_location()
self.redraw()
def set_align_y(self, i):
self.align_vert = i
def set_align_y(self, align_vert):
self.align_vert = align_vert
self.force_location()
self.redraw()
def col(self, c, a=1.0):
self.context.set_source_rgba(c[0], c[1], c[2], c[3] * a)
def col(self, col, alpha=1.0):
self.context.set_source_rgba(col[0], col[1], col[2], col[3] * alpha)
def set_force_xshape(self, force):
self.force_xshape = force

View file

@ -10,7 +10,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""Settings tab parent class. Helpful if we need more overlay types without copy-and-pasting too much code"""
"""
Settings tab parent class. Helpful if we need more
overlay types without copy-and-pasting too much code
"""
import os
import logging
import gi
@ -26,13 +29,16 @@ except ModuleNotFoundError:
class SettingsWindow(Gtk.VBox):
"""Settings tab parent class. Helpful if we need more overlay types without copy-and-pasting too much code"""
"""
Settings tab parent class. Helpful if we need more
overlay types without copy-and-pasting too much code
"""
def __init__(self):
Gtk.VBox.__init__(self)
self.placement_window = None
self.configDir = None
self.configFile = None
self.config_dir = None
self.config_file = None
self.overlay = None
self.floating_x = None
self.floating_y = None
@ -40,20 +46,20 @@ class SettingsWindow(Gtk.VBox):
self.floating_h = None
def init_config(self):
self.configDir = os.path.join(xdg_config_home, "discover_overlay")
os.makedirs(self.configDir, exist_ok=True)
self.configFile = os.path.join(self.configDir, "config.ini")
self.config_dir = os.path.join(xdg_config_home, "discover_overlay")
os.makedirs(self.config_dir, exist_ok=True)
self.config_file = os.path.join(self.config_dir, "config.ini")
self.read_config()
def close_window(self, _a=None, _b=None):
if self.placement_window:
(x, y) = self.placement_window.get_position()
(w, h) = self.placement_window.get_size()
self.floating_x = x
self.floating_y = y
self.floating_w = w
self.floating_h = h
self.overlay.set_floating(True, x, y, w, h)
(pos_x, pos_y) = self.placement_window.get_position()
(width, height) = self.placement_window.get_size()
self.floating_x = pos_x
self.floating_y = pos_y
self.floating_w = width
self.floating_h = height
self.overlay.set_floating(True, pos_x, pos_y, width, height)
self.save_config()
self.placement_window.close()
self.placement_window = None

View file

@ -16,7 +16,7 @@ from .voice_settings import VoiceSettingsWindow
from .text_settings import TextSettingsWindow
from .general_settings import GeneralSettingsWindow
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Gtk
@ -36,26 +36,26 @@ class MainSettingsWindow(Gtk.Window):
self.set_default_size(280, 180)
# Create
nb = Gtk.Notebook()
notebook = Gtk.Notebook()
# nb.set_tab_pos(Gtk.POS_TOP)
self.voice_settings = VoiceSettingsWindow(self.voice_overlay)
nb.append_page(self.voice_settings)
nb.set_tab_label_text(self.voice_settings, "Voice")
notebook.append_page(self.voice_settings)
notebook.set_tab_label_text(self.voice_settings, "Voice")
self.text_settings = TextSettingsWindow(self.text_overlay)
nb.append_page(self.text_settings)
nb.set_tab_label_text(self.text_settings, "Text")
notebook.append_page(self.text_settings)
notebook.set_tab_label_text(self.text_settings, "Text")
self.core_settings = GeneralSettingsWindow(
self.text_overlay, self.voice_overlay)
nb.append_page(self.core_settings)
nb.set_tab_label_text(self.core_settings, "Core")
self.add(nb)
self.nb = nb
notebook.append_page(self.core_settings)
notebook.set_tab_label_text(self.core_settings, "Core")
self.add(notebook)
self.notebook = notebook
def close_window(self, a=None, b=None):
self.text_settings.close_window(a, b)
self.voice_settings.close_window(a, b)
self.core_settings.close_window(a, b)
def close_window(self, widget=None, event=None):
self.text_settings.close_window(widget, event)
self.voice_settings.close_window(widget, event)
self.core_settings.close_window(widget, event)
self.hide()
return True
@ -63,5 +63,5 @@ class MainSettingsWindow(Gtk.Window):
self.voice_settings.present_settings()
self.text_settings.present_settings()
self.core_settings.present_settings()
self.nb.show()
self.notebook.show()
self.show()

View file

@ -20,7 +20,7 @@ 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
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Pango, PangoCairo
@ -47,20 +47,20 @@ class TextOverlayWindow(OverlayWindow):
self.fg_col = [1.0, 1.0, 1.0, 1.0]
self.attachment = {}
self.imgList = []
self.imgFinder = re.compile(r"`")
self.image_list = []
self.img_finder = re.compile(r"`")
self.set_title("Discover Text")
def set_text_time(self, t):
self.text_time = t
def set_text_time(self, timer):
self.text_time = timer
def set_text_list(self, tlist, alt):
def set_text_list(self, tlist, altered):
self.content = tlist
if alt:
if altered:
self.redraw()
def set_enabled(self, en):
if en:
def set_enabled(self, enabled):
if enabled:
self.show_all()
else:
self.hide()
@ -73,12 +73,12 @@ class TextOverlayWindow(OverlayWindow):
self.bg_col = bg_col
self.redraw()
def set_show_attach(self, att):
self.show_attach = att
def set_show_attach(self, attachment):
self.show_attach = attachment
self.redraw()
def set_popup_style(self, b):
self.popup_style = b
def set_popup_style(self, boolean):
self.popup_style = boolean
def set_font(self, name, size):
self.text_font = name
@ -88,48 +88,50 @@ class TextOverlayWindow(OverlayWindow):
self.pango_rect.height = self.text_size * Pango.SCALE
self.redraw()
def make_line(self, msg):
def make_line(self, message):
ret = ""
if isinstance(msg, list):
for a in msg:
ret = "%s%s" % (ret, self.make_line(a))
elif isinstance(msg, str):
ret = msg
elif msg['type'] == 'strong':
ret = "<b>%s</b>" % (self.make_line(msg['content']))
elif msg['type'] == 'text':
ret = self.santize_string(msg['content'])
elif msg['type'] == 'link':
ret = "<u>%s</u>" % (self.make_line(msg['content']))
elif msg['type'] == 'emoji':
if 'surrogate' in msg:
if isinstance(message, list):
for inner_message in message:
ret = "%s%s" % (ret, self.make_line(inner_message))
elif isinstance(message, str):
ret = message
elif message['type'] == 'strong':
ret = "<b>%s</b>" % (self.make_line(message['content']))
elif message['type'] == 'text':
ret = self.sanitize_string(message['content'])
elif message['type'] == 'link':
ret = "<u>%s</u>" % (self.make_line(message['content']))
elif message['type'] == 'emoji':
if 'surrogate' in message:
# ['src'] is SVG URL
# ret = msg
ret = msg['surrogate']
ret = message['surrogate']
else:
### Add Image ###
url = ("https://cdn.discordapp.com/emojis/%s.png?v=1" %
(msg['emojiId']))
(message['emojiId']))
img = {"url": url}
self.imgList.append(img)
self.image_list.append(img)
ret = "`"
elif msg['type'] == 'inlineCode' or msg['type'] == 'codeBlock' or msg['type'] == 'blockQuote':
elif (message['type'] == 'inlineCode' or
message['type'] == 'codeBlock' or
message['type'] == 'blockQuote'):
ret = "<span font_family=\"monospace\" background=\"#0004\">%s</span>" % (
self.make_line(msg['content']))
elif msg['type'] == 'u':
ret = "<u>%s</u>" % (self.make_line(msg['content']))
elif msg['type'] == 'em':
ret = "<i>%s</i>" % (self.make_line(msg['content']))
elif msg['type'] == 's':
ret = "<s>%s</s>" % (self.make_line(msg['content']))
elif msg['type'] == 'channel':
ret = self.make_line(msg['content'])
elif msg['type'] == 'mention':
ret = self.make_line(msg['content'])
elif msg['type'] == 'br':
self.make_line(message['content']))
elif message['type'] == 'u':
ret = "<u>%s</u>" % (self.make_line(message['content']))
elif message['type'] == 'em':
ret = "<i>%s</i>" % (self.make_line(message['content']))
elif message['type'] == 's':
ret = "<s>%s</s>" % (self.make_line(message['content']))
elif message['type'] == 'channel':
ret = self.make_line(message['content'])
elif message['type'] == 'mention':
ret = self.make_line(message['content'])
elif message['type'] == 'br':
ret = '\n'
else:
logging.error("Unknown text type : %s", msg["type"])
logging.error("Unknown text type : %s", message["type"])
return ret
def recv_attach(self, identifier, pix):
@ -139,7 +141,7 @@ class TextOverlayWindow(OverlayWindow):
def overlay_draw(self, _w, context, data=None):
self.context = context
context.set_antialias(cairo.ANTIALIAS_GOOD)
(w, h) = self.get_size()
(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)
@ -150,19 +152,19 @@ class TextOverlayWindow(OverlayWindow):
# The window is full-screen regardless of what the user has selected. Because Wayland
# We need to set a clip and a transform to imitate original behaviour
w = self.w
h = self.h
context.translate(self.x, self.y)
context.rectangle(0, 0, w, h)
width = self.width
height = self.height
context.translate(self.pos_x, self.pos_y)
context.rectangle(0, 0, width, height)
context.clip()
cy = h
current_y = height
tnow = time.time()
for line in reversed(self.content):
if self.popup_style and tnow - line['time'] > self.text_time:
break
out_line = ""
self.imgList = []
self.image_list = []
col = "#fff"
if 'nick_col' in line and line['nick_col']:
@ -170,98 +172,106 @@ class TextOverlayWindow(OverlayWindow):
for in_line in line['content']:
out_line = "%s%s" % (out_line, self.make_line(in_line))
if line['attach'] and self.show_attach:
at = line['attach'][0]
url = at['url']
attachment = line['attach'][0]
url = attachment['url']
if url in self.attachment:
cy = self.draw_attach(cy, url)
current_y = self.draw_attach(current_y, url)
else:
get_surface(self.recv_attach,
url,
url, None)
# cy = self.draw_text(cy, "%s" % (line['attach']))
cy = self.draw_text(cy, "<span foreground='%s'>%s</span>: %s" % (self.santize_string(col),
self.santize_string(line["nick"]), out_line))
if cy <= 0:
message = "<span foreground='%s'>%s</span>: %s" % (self.sanitize_string(col),
self.sanitize_string(
line["nick"]),
out_line)
current_y = self.draw_text(current_y, message)
if current_y <= 0:
# We've done enough
break
if self.is_wayland:
context.restore()
def draw_attach(self, y, url):
def draw_attach(self, pos_y, url):
if url in self.attachment and self.attachment[url]:
pix = self.attachment[url]
iw = pix.get_width()
ih = pix.get_height()
iw = min(iw, self.w)
ih = min(ih, (self.h * .7))
(_ax, _ay, _aw, ah) = get_aspected_size(pix, iw, ih)
image_width = min(pix.get_width(), self.width)
image_height = min(pix.get_height(), (self.height * .7))
(_ax, _ay, _aw, aspect_height) = get_aspected_size(
pix, image_width, image_height)
self.col(self.bg_col)
self.context.rectangle(0, y - ah, self.w, ah)
self.context.rectangle(0, pos_y - aspect_height,
self.width, aspect_height)
self.context.fill()
self.context.set_operator(cairo.OPERATOR_OVER)
_new_w, new_h = draw_img_to_rect(
pix, self.context, 0, y - ih, iw, ih, aspect=True)
return y - new_h
return y
pix, self.context, 0, pos_y - image_height, image_width, image_height, aspect=True)
return pos_y - new_h
return pos_y
def draw_text(self, y, text):
def draw_text(self, pos_y, text):
layout = self.create_pango_layout(text)
layout.set_markup(text, -1)
attr = layout.get_attributes()
layout.set_width(Pango.SCALE * self.w)
layout.set_width(Pango.SCALE * self.width)
layout.set_spacing(Pango.SCALE * 3)
if(self.text_font):
if self.text_font:
font = Pango.FontDescription(
"%s %s" % (self.text_font, self.text_size))
layout.set_font_description(font)
_tw, th = layout.get_pixel_size()
_tw, text_height = layout.get_pixel_size()
self.col(self.bg_col)
self.context.rectangle(0, y - th, self.w, th)
self.context.rectangle(0, pos_y - text_height, self.width, text_height)
self.context.fill()
self.context.set_operator(cairo.OPERATOR_OVER)
self.col(self.fg_col)
self.context.move_to(0, y - th)
self.context.move_to(0, pos_y - text_height)
PangoCairo.context_set_shape_renderer(
self.get_pango_context(), self.render_custom, None)
text = layout.get_text()
count = 0
for loc in self.imgFinder.finditer(text):
for loc in self.img_finder.finditer(text):
idx = loc.start()
if len(self.imgList) <= count:
if len(self.image_list) <= count:
break # We fucked up. Who types ` anyway
# url = self.imgList[count]
at = Pango.attr_shape_new_with_data(
attachment = Pango.attr_shape_new_with_data(
self.pango_rect, self.pango_rect, count, None)
at.start_index = idx
at.end_index = idx + 1
attr.insert(at)
attachment.start_index = idx
attachment.end_index = idx + 1
attr.insert(attachment)
count += 1
layout.set_attributes(attr)
PangoCairo.show_layout(self.context, layout)
return y - th
return pos_y - text_height
def render_custom(self, ctx, shape, path, _data):
key = self.imgList[shape.data]['url']
key = self.image_list[shape.data]['url']
if key not in self.attachment:
get_surface(self.recv_attach,
key,
key, None)
return
pix = self.attachment[key]
(x, y) = ctx.get_current_point()
draw_img_to_rect(pix, ctx, x, y - self.text_size, self.text_size,
(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 santize_string(self, string):
def sanitize_string(self, string):
# I hate that Pango has nothing for this.
return string.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("'", "&#39;").replace("\"", "&#34;")
string.replace("&", "&amp;")
string.replace("<", "&lt;")
string .replace(">", "&gt;")
string.replace("'", "&#39;")
string.replace("\"", "&#34;")
return string

View file

@ -20,7 +20,7 @@ from .draggable_window_wayland import DraggableWindowWayland
from .settings import SettingsWindow
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Gtk, Gdk, Pango
@ -80,26 +80,26 @@ class TextSettingsWindow(SettingsWindow):
# if no guild is specified, populate channel list with every channel from each guild
if self.guild == GUILD_DEFAULT_VALUE:
c_model.append([guild_name, False])
for c in self.list_channels_keys:
chan = self.list_channels[c]
for channel_key in self.list_channels_keys:
chan = self.list_channels[channel_key]
if chan['guild_id'] == guild_id:
c_model.append([chan["name"], True])
self.channel_lookup.append(c)
self.channel_lookup.append(channel_key)
# if a guild is specified, poulate channel list with every channel from *just that guild*
if self.guild != GUILD_DEFAULT_VALUE:
for c in self.list_channels_keys:
chan = self.list_channels[c]
for channel_key in self.list_channels_keys:
chan = self.list_channels[channel_key]
if chan['guild_id'] == self.guild:
c_model.append([chan["name"], True])
self.channel_lookup.append(c)
self.channel_lookup.append(channel_key)
self.channel_widget.set_model(c_model)
self.channel_model = c_model
idx = 0
for c in self.channel_lookup:
if c == self.channel:
for channel in self.channel_lookup:
if channel == self.channel:
self.ignore_channel_change = True
self.channel_widget.set_active(idx)
self.ignore_channel_change = False
@ -180,7 +180,7 @@ class TextSettingsWindow(SettingsWindow):
def read_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
self.enabled = config.getboolean("text", "enabled", fallback=False)
self.align_x = config.getboolean("text", "rightalign", fallback=True)
self.align_y = config.getint("text", "topalign", fallback=2)
@ -222,7 +222,7 @@ class TextSettingsWindow(SettingsWindow):
def save_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
if not config.has_section("text"):
config.add_section("text")
@ -246,7 +246,7 @@ class TextSettingsWindow(SettingsWindow):
if self.font:
config.set("text", "font", self.font)
with open(self.configFile, 'w') as file:
with open(self.config_file, 'w') as file:
config.write(file)
def create_gui(self):
@ -311,9 +311,9 @@ class TextSettingsWindow(SettingsWindow):
monitor = Gtk.ComboBox.new_with_model(monitor_store)
monitor.set_active(self.get_monitor_index(self.monitor))
monitor.connect("changed", self.change_monitor)
rt = Gtk.CellRendererText()
monitor.pack_start(rt, True)
monitor.add_attribute(rt, "text", 0)
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"])
@ -321,9 +321,9 @@ class TextSettingsWindow(SettingsWindow):
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)
rt = Gtk.CellRendererText()
align_x.pack_start(rt, True)
align_x.add_attribute(rt, "text", 0)
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"])
@ -332,9 +332,9 @@ class TextSettingsWindow(SettingsWindow):
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)
rt = Gtk.CellRendererText()
align_y.pack_start(rt, True)
align_y.add_attribute(rt, "text", 0)
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")
@ -346,19 +346,19 @@ class TextSettingsWindow(SettingsWindow):
channel = Gtk.ComboBox.new()
channel.connect("changed", self.change_channel)
rt = Gtk.CellRendererText()
channel.pack_start(rt, True)
channel.add_attribute(rt, "text", 0)
channel.add_attribute(rt, 'sensitive', 1)
renderer_text = Gtk.CellRendererText()
channel.pack_start(renderer_text, True)
channel.add_attribute(renderer_text, "text", 0)
channel.add_attribute(renderer_text, 'sensitive', 1)
guild_label = Gtk.Label.new("Server")
guild = Gtk.ComboBox.new()
guild.connect("changed", self.change_guild)
rt = Gtk.CellRendererText()
guild.pack_start(rt, True)
guild.add_attribute(rt, "text", 0)
guild.add_attribute(rt, 'sensitive', 1)
renderer_text = Gtk.CellRendererText()
guild.pack_start(renderer_text, True)
guild.add_attribute(renderer_text, "text", 0)
guild.add_attribute(renderer_text, 'sensitive', 1)
# Show Attachments
show_attach_label = Gtk.Label.new("Show Attachments")
@ -406,10 +406,10 @@ class TextSettingsWindow(SettingsWindow):
def change_font(self, button):
font = button.get_font()
desc = Pango.FontDescription.from_string(font)
s = desc.get_size()
size = desc.get_size()
if not desc.get_size_is_absolute():
s = s / Pango.SCALE
self.overlay.set_font(desc.get_family(), s)
size = size / Pango.SCALE
self.overlay.set_font(desc.get_family(), size)
self.font = desc.to_string()
self.save_config()
@ -418,9 +418,9 @@ class TextSettingsWindow(SettingsWindow):
if self.ignore_channel_change:
return
c = self.channel_lookup[button.get_active()]
self.connector.start_listening_text(c)
self.channel = c
channel = self.channel_lookup[button.get_active()]
self.connector.start_listening_text(channel)
self.channel = channel
self.save_config()
def change_guild(self, button):
@ -433,12 +433,12 @@ class TextSettingsWindow(SettingsWindow):
def change_placement(self, button):
if self.placement_window:
(x, y, w, h) = self.placement_window.get_coords()
self.floating_x = x
self.floating_y = y
self.floating_w = w
self.floating_h = h
self.overlay.set_floating(True, x, y, w, h)
(pos_x, pos_y, width, height) = self.placement_window.get_coords()
self.floating_x = pos_x
self.floating_y = pos_y
self.floating_w = width
self.floating_h = height
self.overlay.set_floating(True, pos_x, pos_y, width, height)
self.save_config()
if not self.overlay.is_wayland:
button.set_label("Place Window")
@ -448,13 +448,13 @@ class TextSettingsWindow(SettingsWindow):
else:
if self.overlay.is_wayland:
self.placement_window = DraggableWindowWayland(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
pos_x=self.floating_x, pos_y=self.floating_y,
width=self.floating_w, height=self.floating_h,
message="Place & resize this window then press Green!", settings=self)
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
pos_x=self.floating_x, pos_y=self.floating_y,
width=self.floating_w, height=self.floating_h,
message="Place & resize this window then press Save!", settings=self)
if not self.overlay.is_wayland:
button.set_label("Save this position")
@ -535,19 +535,19 @@ class TextSettingsWindow(SettingsWindow):
return self.channel
def change_bg(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_bg(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_bg(colour)
self.bg_col = c
self.bg_col = colour
self.save_config()
def change_fg(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_fg(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_fg(colour)
self.fg_col = c
self.fg_col = colour
self.save_config()
def change_show_attach(self, button):

View file

@ -54,20 +54,20 @@ class VoiceOverlayWindow(OverlayWindow):
'def', self.avatar_size)
self.set_title("Discover Voice")
def set_bg(self, bg):
self.norm_col = bg
def set_bg(self, background_colour):
self.norm_col = background_colour
self.redraw()
def set_fg(self, fg):
self.text_col = fg
def set_fg(self, foreground_colour):
self.text_col = foreground_colour
self.redraw()
def set_tk(self, tk):
self.talk_col = tk
def set_tk(self, talking_colour):
self.talk_col = talking_colour
self.redraw()
def set_mt(self, mt):
self.mute_col = mt
def set_mt(self, mute_colour):
self.mute_col = mute_colour
self.redraw()
def set_avatar_size(self, size):
@ -116,11 +116,11 @@ class VoiceOverlayWindow(OverlayWindow):
def set_norm_col(self):
self.col(self.norm_col)
def set_talk_col(self, a=1.0):
self.col(self.talk_col, a)
def set_talk_col(self, alpha=1.0):
self.col(self.talk_col, alpha)
def set_mute_col(self, a=1.0):
self.col(self.mute_col, a)
def set_mute_col(self, alpha=1.0):
self.col(self.mute_col, alpha)
def set_user_list(self, userlist, alt):
self.userlist = userlist
@ -137,10 +137,10 @@ class VoiceOverlayWindow(OverlayWindow):
else: # Name sort
self.userlist.sort(key=lambda x: x["friendlyname"])
screen = self.get_screen()
c = screen.is_composited()
if not self.compositing == c:
# Check if composite state has changed
if not self.compositing == screen.is_composited():
alt = True
self.compositing = c
self.compositing = screen.is_composited()
if alt:
self.redraw()
@ -154,7 +154,7 @@ class VoiceOverlayWindow(OverlayWindow):
self.context = context
context.set_antialias(cairo.ANTIALIAS_GOOD)
# Get size of window
(w, h) = self.get_size()
(width, height) = self.get_size()
# Make background transparent
self.set_wind_col()
# Don't layer drawing over each other, always replace
@ -166,10 +166,10 @@ class VoiceOverlayWindow(OverlayWindow):
# The window is full-screen regardless of what the user has selected. Because Wayland
# We need to set a clip and a transform to imitate original behaviour
w = self.w
h = self.h
context.translate(self.x, self.y)
context.rectangle(0, 0, w, h)
width = self.width
height = self.height
context.translate(self.pos_x, self.pos_y)
context.rectangle(0, 0, width, height)
context.clip()
context.set_operator(cairo.OPERATOR_OVER)
@ -206,25 +206,25 @@ class VoiceOverlayWindow(OverlayWindow):
self.users_to_draw.insert(0, self_user)
# Calculate height needed to show overlay
height = (len(self.users_to_draw) * self.avatar_size) + \
needed_height = (len(self.users_to_draw) * self.avatar_size) + \
(len(self.users_to_draw) + 1) * self.icon_spacing
# Choose where to start drawing
rh = 0 + self.vert_edge_padding
current_y = 0 + self.vert_edge_padding
if self.align_vert == 1:
# Ignore padding?
rh = (h / 2) - (height / 2)
current_y = (height / 2) - (needed_height / 2)
elif self.align_vert == 2:
rh = h - height - self.vert_edge_padding
current_y = height - needed_height - self.vert_edge_padding
for user in self.users_to_draw:
self.draw_avatar(context, user, rh)
self.draw_avatar(context, user, current_y)
# Shift the relative position down to next location
rh += self.avatar_size + self.icon_spacing
current_y += self.avatar_size + self.icon_spacing
# Don't hold a ref
if self.is_wayland:
context.restore()
# Don't hold a ref
self.context = None
def recv_avatar(self, identifier, pix):
@ -238,7 +238,7 @@ class VoiceOverlayWindow(OverlayWindow):
if id in self.avatars:
del self.avatars[identifier]
def draw_avatar(self, context, user, y):
def draw_avatar(self, context, user, pos_y):
# Ensure pixbuf for avatar
if user["id"] not in self.avatars and user["avatar"]:
url = "https://cdn.discordapp.com/avatars/%s/%s.jpg" % (
@ -249,7 +249,7 @@ class VoiceOverlayWindow(OverlayWindow):
# Set the key with no value to avoid spamming requests
self.avatars[user["id"]] = None
c = None
colour = None
mute = False
deaf = False
@ -258,94 +258,125 @@ class VoiceOverlayWindow(OverlayWindow):
if "deaf" in user and user["deaf"]:
deaf = True
if "speaking" in user and user["speaking"] and not deaf and not mute:
c = self.talk_col
colour = self.talk_col
pix = None
if user["id"] in self.avatars:
pix = self.avatars[user["id"]]
if self.align_right:
if not self.icon_only:
self.draw_text(
context, user["friendlyname"], self.w - self.avatar_size - self.horz_edge_padding, y)
context, user["friendlyname"],
self.width - self.avatar_size - self.horz_edge_padding,
pos_y
)
self.draw_avatar_pix(
context, pix, self.w - self.avatar_size - self.horz_edge_padding, y, c)
context, pix,
self.width - self.avatar_size - self.horz_edge_padding,
pos_y,
colour
)
if deaf:
self.draw_deaf(context, self.w - self.avatar_size -
self.horz_edge_padding, y)
self.draw_deaf(context, self.width - self.avatar_size -
self.horz_edge_padding, pos_y)
elif mute:
self.draw_mute(context, self.w - self.avatar_size -
self.horz_edge_padding, y)
self.draw_mute(context, self.width - self.avatar_size -
self.horz_edge_padding, pos_y)
else:
if not self.icon_only:
self.draw_text(
context, user["friendlyname"], self.avatar_size + self.horz_edge_padding, y)
context,
user["friendlyname"],
self.avatar_size + self.horz_edge_padding,
pos_y
)
self.draw_avatar_pix(
context, pix, self.horz_edge_padding, y, c)
context, pix, self.horz_edge_padding, pos_y, colour
)
if deaf:
self.draw_deaf(context, self.horz_edge_padding, y)
self.draw_deaf(context, self.horz_edge_padding, pos_y)
elif mute:
self.draw_mute(context, self.horz_edge_padding, y)
self.draw_mute(context, self.horz_edge_padding, pos_y)
def draw_text(self, context, string, x, y):
def draw_text(self, context, string, pos_x, pos_y):
if self.text_font:
context.set_font_face(cairo.ToyFontFace(
self.text_font, cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL))
context.set_font_size(self.text_size)
_xb, _yb, w, h, _dx, _dy = context.text_extents(string)
ho = (self.avatar_size / 2) - (h / 2)
_xb, _yb, width, height, _dx, _dy = context.text_extents(string)
height_offset = (self.avatar_size / 2) - (height / 2)
if self.align_right:
context.move_to(0, 0)
self.set_norm_col()
context.rectangle(x - w - (self.text_pad * 2), y + ho - self.text_pad,
w + (self.text_pad * 4), h + (self.text_pad * 2))
context.rectangle(
pos_x - width - (self.text_pad * 2),
pos_y + height_offset - self.text_pad,
width + (self.text_pad * 4),
height + (self.text_pad * 2)
)
context.fill()
self.set_text_col()
context.move_to(x - w - self.text_pad, y + ho + h)
context.move_to(
pos_x - width - self.text_pad,
pos_y + height_offset + height
)
context.show_text(string)
else:
context.move_to(0, 0)
self.set_norm_col()
context.rectangle(x - (self.text_pad * 2), y + ho - self.text_pad,
w + (self.text_pad * 4), h + (self.text_pad * 2))
context.rectangle(
pos_x - (self.text_pad * 2),
pos_y + height_offset - self.text_pad,
width + (self.text_pad * 4),
height + (self.text_pad * 2)
)
context.fill()
self.set_text_col()
context.move_to(x + self.text_pad, y + ho + h)
context.move_to(pos_x + self.text_pad,
pos_y + height_offset + height)
context.show_text(string)
def draw_avatar_pix(self, context, pixbuf, x, y, c):
def draw_avatar_pix(self, context, pixbuf, pos_x, pos_y, border_colour):
if not pixbuf:
pixbuf = self.def_avatar
if not pixbuf:
return
context.move_to(x, y)
context.move_to(pos_x, pos_y)
context.save()
if self.round_avatar:
context.arc(x + (self.avatar_size / 2), y +
context.arc(pos_x + (self.avatar_size / 2), pos_y +
(self.avatar_size / 2), self.avatar_size / 2, 0, 2 * math.pi)
context.clip()
self.set_norm_col()
context.set_operator(cairo.OPERATOR_SOURCE)
context.rectangle(x, y, self.avatar_size, self.avatar_size)
context.rectangle(pos_x, pos_y, self.avatar_size, self.avatar_size)
context.fill()
draw_img_to_rect(pixbuf, context, x, y,
draw_img_to_rect(pixbuf, context, pos_x, pos_y,
self.avatar_size, self.avatar_size)
context.restore()
if c:
if border_colour:
if self.round_avatar:
context.arc(x + (self.avatar_size / 2), y +
(self.avatar_size / 2), self.avatar_size / 2, 0, 2 * math.pi)
self.col(c)
context.arc(
pos_x + (self.avatar_size / 2),
pos_y + (self.avatar_size / 2),
self.avatar_size / 2,
0, 2 * math.pi
)
self.col(border_colour)
context.stroke()
else:
context.rectangle(x, y, self.avatar_size, self.avatar_size)
self.col(c)
context.rectangle(
pos_x, pos_y,
self.avatar_size, self.avatar_size
)
self.col(border_colour)
context.stroke()
def draw_mute(self, context, x, y):
def draw_mute(self, context, pos_x, pos_y):
context.save()
context.translate(x, y)
context.translate(pos_x, pos_y)
context.scale(self.avatar_size, self.avatar_size)
self.set_mute_col()
context.save()
@ -397,9 +428,9 @@ class VoiceOverlayWindow(OverlayWindow):
context.restore()
def draw_deaf(self, context, x, y):
def draw_deaf(self, context, pos_x, pos_y):
context.save()
context.translate(x, y)
context.translate(pos_x, pos_y)
context.scale(self.avatar_size, self.avatar_size)
self.set_mute_col()
context.save()

View file

@ -18,7 +18,7 @@ from .draggable_window import DraggableWindow
from .draggable_window_wayland import DraggableWindowWayland
from .settings import SettingsWindow
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order
from gi.repository import Gtk, Gdk, Pango
@ -70,7 +70,7 @@ class VoiceSettingsWindow(SettingsWindow):
def read_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
self.align_x = config.getboolean("main", "rightalign", fallback=True)
self.align_y = config.getint("main", "topalign", fallback=1)
self.bg_col = json.loads(config.get(
@ -130,14 +130,14 @@ class VoiceSettingsWindow(SettingsWindow):
if self.font:
desc = Pango.FontDescription.from_string(self.font)
s = desc.get_size()
size = desc.get_size()
if not desc.get_size_is_absolute():
s = s / Pango.SCALE
self.overlay.set_font(desc.get_family(), s)
size = size / Pango.SCALE
self.overlay.set_font(desc.get_family(), size)
def save_config(self):
config = ConfigParser(interpolation=None)
config.read(self.configFile)
config.read(self.config_file)
if not config.has_section("main"):
config.add_section("main")
@ -168,7 +168,7 @@ class VoiceSettingsWindow(SettingsWindow):
config.set("main", "floating_h", "%s" % (self.floating_h))
config.set("main", "order", "%s" % (self.order))
with open(self.configFile, 'w') as file:
with open(self.config_file, 'w') as file:
config.write(file)
def create_gui(self):
@ -231,9 +231,9 @@ class VoiceSettingsWindow(SettingsWindow):
monitor = Gtk.ComboBox.new_with_model(monitor_store)
monitor.set_active(self.get_monitor_index(self.monitor))
monitor.connect("changed", self.change_monitor)
rt = Gtk.CellRendererText()
monitor.pack_start(rt, True)
monitor.add_attribute(rt, "text", 0)
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"])
@ -241,9 +241,9 @@ class VoiceSettingsWindow(SettingsWindow):
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)
rt = Gtk.CellRendererText()
align_x.pack_start(rt, True)
align_x.add_attribute(rt, "text", 0)
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"])
@ -252,9 +252,9 @@ class VoiceSettingsWindow(SettingsWindow):
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)
rt = Gtk.CellRendererText()
align_y.pack_start(rt, True)
align_y.add_attribute(rt, "text", 0)
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")
@ -329,9 +329,9 @@ class VoiceSettingsWindow(SettingsWindow):
order = Gtk.ComboBox.new_with_model(order_store)
order.set_active(self.order)
order.connect("changed", self.change_order)
rt = Gtk.CellRendererText()
order.pack_start(rt, True)
order.add_attribute(rt, "text", 0)
renderer_text = Gtk.CellRendererText()
order.pack_start(renderer_text, True)
order.add_attribute(renderer_text, "text", 0)
box.attach(font_label, 0, 0, 1, 1)
box.attach(font, 1, 0, 1, 1)
@ -374,12 +374,12 @@ class VoiceSettingsWindow(SettingsWindow):
def change_placement(self, button):
if self.placement_window:
(x, y, w, h) = self.placement_window.get_coords()
self.floating_x = x
self.floating_y = y
self.floating_w = w
self.floating_h = h
self.overlay.set_floating(True, x, y, w, h)
(pos_x, pos_y, width, height) = self.placement_window.get_coords()
self.floating_x = pos_x
self.floating_y = pos_y
self.floating_w = width
self.floating_h = height
self.overlay.set_floating(True, pos_x, pos_y, width, height)
self.save_config()
if not self.overlay.is_wayland:
button.set_label("Place Window")
@ -388,13 +388,13 @@ class VoiceSettingsWindow(SettingsWindow):
else:
if self.overlay.is_wayland:
self.placement_window = DraggableWindowWayland(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
pos_x=self.floating_x, pos_y=self.floating_y,
width=self.floating_w, height=self.floating_h,
message="Place & resize this window then press Green!", settings=self)
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
pos_x=self.floating_x, pos_y=self.floating_y,
width=self.floating_w, height=self.floating_h,
message="Place & resize this window then press Save!", settings=self)
if not self.overlay.is_wayland:
button.set_label("Save this position")
@ -428,44 +428,44 @@ class VoiceSettingsWindow(SettingsWindow):
def change_font(self, button):
font = button.get_font()
desc = Pango.FontDescription.from_string(font)
s = desc.get_size()
size = desc.get_size()
if not desc.get_size_is_absolute():
s = s / Pango.SCALE
self.overlay.set_font(desc.get_family(), s)
size = size / Pango.SCALE
self.overlay.set_font(desc.get_family(), size)
self.font = desc.to_string()
self.save_config()
def change_bg(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_bg(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_bg(colour)
self.bg_col = c
self.bg_col = colour
self.save_config()
def change_fg(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_fg(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_fg(colour)
self.fg_col = c
self.fg_col = colour
self.save_config()
def change_tk(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_tk(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_tk(colour)
self.tk_col = c
self.tk_col = colour
self.save_config()
def change_mt(self, button):
c = button.get_rgba()
c = [c.red, c.green, c.blue, c.alpha]
self.overlay.set_mt(c)
colour = button.get_rgba()
colour = [colour.red, colour.green, colour.blue, colour.alpha]
self.overlay.set_mt(colour)
self.mt_col = c
self.mt_col = colour
self.save_config()
def change_avatar_size(self, button):