aboutsummaryrefslogtreecommitdiff
path: root/logout-manager-tcl.py
diff options
context:
space:
mode:
Diffstat (limited to 'logout-manager-tcl.py')
-rwxr-xr-xlogout-manager-tcl.py113
1 files changed, 23 insertions, 90 deletions
diff --git a/logout-manager-tcl.py b/logout-manager-tcl.py
index 5b0d29d..74c914b 100755
--- a/logout-manager-tcl.py
+++ b/logout-manager-tcl.py
@@ -28,25 +28,16 @@
# package: RPM | DPKG
# tkinter: python36-tkinter | python3-tk
# PIL: python36-pillow-tk | python3-pil.imagetk
-# cairo: python36-cairo | python3-cairo
-# Rsvg: python36-gobject | python3-gobject
-from gi import require_version
-require_version('Rsvg', '2.0')
-from gi.repository import Rsvg
-import os, sys, configparser, glob, re, cairo
+import glob, re
import tkinter as tk
-import tkinter.ttk as ttk
from functools import partial
from pathlib import Path
+from sys import path
+# loading PIL.ImageTk after tkinter makes ImageTk use the PIL version, which supports PNG. This is important on tcl < 8.6 (that is, el7)
from PIL import Image, ImageTk
-sys.path.append("/home/bgirton/dev/logout-manager")
+path.append("/home/bgirton/dev/logout-manager")
import lmlib
-#if TkVersion < 8.6:
-# USE_PRIVATE_TCL_IMAGES = 1
-# print("Loading private PIL translation layter")
-# def PhotoImage_from_png(file):
-# return ImageTk.PhotoImage(file=file)
config = lmlib.Initialize_config()
actions = lmlib.Actions
@@ -54,48 +45,6 @@ actions = lmlib.Actions
# graphical classes and functions
print("Loading graphics...")
-def _alpha_blending(rgba, back):
- "Return a rgb tuple composed from a rgba and back(ground) tuple/list."
- paired = zip(rgba[:-1], back)
- alpha = rgba[-1]
- tmp = list()
- for upper, lower in paired:
- blend = (((255 - alpha) * lower) + (alpha * upper)) / 255
- tmp.append(blend)
-
- return(tuple(tmp))
-
-def convert(bgra_buffer, width, height):
- "Convert bgra buffer to photoimage put"
- idx = 0
- end = len(bgra_buffer)
- arguments = list()
-
- while idx < end:
- rgba = (ord(bgra_buffer[idx + 2]),
- ord(bgra_buffer[idx + 1]),
- ord(bgra_buffer[idx + 0]),
- ord(bgra_buffer[idx + 3]))
- back = (255, 255, 255)
- rgb = _alpha_blending(rgba, back)
- arguments += rgb
- idx += 4
-
- template = ' '.join(height *['{%s}' % (''.join(width*["#%02x%02x%02x"]))])
- return(template % tuple(arguments))
-
-def photoimage_from_svg(file_path_name):
- '''Return a Tkinter.PhotoImage with the content set to the rendered SVG.'''
- svg = rsvg.Handle(file=file_path_name)
- width, height = svg.get_dimension_data()[:2]
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, int(width), int(height))
- context = cairo.Context(surface)
- svg.render_cairo(context)
- image = tk.PhotoImage(width=width, height=height)
- data = convert(surface.get_data(), width, height)
- image.put(data)
- return(image)
-
class Tooltip:
'''
@@ -255,10 +204,8 @@ def tryint(s):
return s
def sort_sizes(x):
- # I don't even know how this works. I mashed it together from so#46228101
- # WORKS return [tryint(c) for c in re.split('([0-9]+)',x.split("/")[5])]
+ # Original reference so#46228101
value = x.split("/")[5]
- #return int(re.split("[^0-9]+",value)[0]) * 100 + int( re.split("[^0-9]+",value)[1] if len(value.split("@")) >= 2 else 0 )
return mynum(value, "all")
def mynum(x, type = "all"):
@@ -297,11 +244,11 @@ def get_filename_of_icon(name, theme = "hicolor", size = 48, category = "actions
theme = "hicolor"
# first, find all files underneath /usr/share/icons/$THEME/$SIZE
- # WORKHERE, allow a prioritization of category, but tolerate any category if the requested category has no matches but another category does
print("Finding filename of icon, theme=",theme,"category=",category,"name=",name)
- # WORKHERE: this glob affects if scalable/ dir is included. When support for svg is added (which is beyond PIL), need to add a conditional and use a second glob if USE_SVG=1.
+ # FUTUREIMPROVEMENT: this glob affects if scalable/ dir is included. When support for svg is added (which is beyond PIL), need to add a conditional and use a second glob if USE_SVG=1.
+ # to exclude the scalable/ contents, replace dir 5 asterisk with [0-9]*
results = []
- results = glob.glob("/usr/share/icons/"+theme+"/*/"+category+"/"+name+".*")
+ results = glob.glob("/usr/share/icons/"+theme+"/*/"+category+"/"+name+".{png,PNG}")
if len(results) == 0:
# no results with that category, so try all categories
results = glob.glob("/usr/share/icons/"+theme+"/*/*/"+name+".*")
@@ -328,7 +275,7 @@ def get_scaled_icon(icon_name, size = 24, icon_theme = "default", fallback_icon_
#print("Using icon theme",icon_theme)
iconfilename = get_filename_of_icon(name=icon_name, theme=icon_theme, size=size, category=config.get_icon_category())
- # So now that we think we have derived the correct filename...
+ # So now we think we have derived the correct filename
try:
print("Trying icon file",iconfilename)
# try an svg
@@ -340,7 +287,7 @@ def get_scaled_icon(icon_name, size = 24, icon_theme = "default", fallback_icon_
except:
print("Error with icon file.")
return None
- # If I ever add HiDPI stuff, multiple size here by the factor. So, size * 1.25
+ # If I ever add HiDPI support, multiple size here by the factor. So, size * 1.25
photo.thumbnail(size=[size, size])
try:
photo2 = ImageTk.PhotoImage(photo)
@@ -353,46 +300,40 @@ class App:
frame = tk.Frame(master)
frame.grid(row=0)
- self.buttonLock = tk.Button(frame, text="Lock", underline=3, command=partial(actions.lock,config))
- self.buttonLock.grid(row=0,column=0)
- # WORKS master.bind_all("<Alt-k>", something)
- # PASSES 2 params when expecting 1 master.bind_all("<Alt-k>", self.buttonLock.invoke)
+ self.photoLock = get_scaled_icon(config.get_lock_icon(), config.get_icon_size(), config.get_icon_theme())
+ self.buttonLock = tk.Button(frame, text="Lock", underline=3, command=partial(actions.lock,config), image=self.photoLock, compound=tk.LEFT)
master.bind_all("<Alt-k>", partial(actions.lock,config))
+ Tooltip(self.buttonLock, text="Hide session and require authentication to return to it")
+ self.buttonLock.grid(row=0,column=0)
- # WORKS, for basic image loading.
- #self.photoLogout = get_scaled_icon("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png")
- #self.buttonLogout = tk.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=TOP)
- #self.photoLogout1 = Image.open("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png")
- #self.photoLogout1.thumbnail(size=[24,24])
- #self.photoLogout = ImageTk.PhotoImage(self.photoLogout1,size="24x24")
- #self.photoLogout = get_scaled_icon("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png", 24)
- #self.photoLogout = get_scaled_icon("system-log-out", 24, icon_theme="default")
- print("Using configed icon theme:",config.get_icon_theme())
self.photoLogout = get_scaled_icon(config.get_logout_icon(), config.get_icon_size(), config.get_icon_theme())
self.buttonLogout = tk.Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=tk.LEFT)
master.bind_all("<Alt-l>", partial(actions.logout,config))
- Tooltip(self.buttonLogout, text="HERE IS SOMETHING!")
+ Tooltip(self.buttonLogout, text="Close the current user session")
self.buttonLogout.grid(row=0,column=1)
self.photoHibernate = get_scaled_icon(config.get_hibernate_icon(), config.get_icon_size(), config.get_icon_theme())
self.buttonHibernate = tk.Button(frame, text="Hibernate", underline=0, command=lambda: actions.hibernate(config), image=self.photoHibernate, compound=tk.LEFT)
- self.buttonHibernate.grid(row=0,column=2)
master.bind_all("<Alt-h>", partial(actions.hibernate,config))
+ Tooltip(self.buttonHibernate, text="Save state to disk and power off")
+ self.buttonHibernate.grid(row=0,column=2)
self.photoShutdown = get_scaled_icon(config.get_shutdown_icon(), config.get_icon_size(), config.get_icon_theme())
self.buttonShutdown = tk.Button(frame, text="Shutdown", underline=0, command=lambda: actions.shutdown(config), image=self.photoShutdown, compound=tk.LEFT)
- self.buttonShutdown.grid(row=0,column=3)
master.bind_all("<Alt-s>", partial(actions.shutdown,config))
+ Tooltip(self.buttonShutdown, text="Power off the computer")
+ self.buttonShutdown.grid(row=0,column=3)
self.photoReboot = get_scaled_icon(config.get_reboot_icon(), config.get_icon_size(), config.get_icon_theme())
self.buttonReboot = tk.Button(frame, text="Reboot", underline=0, command=lambda: actions.reboot(config), image=self.photoReboot, compound=tk.LEFT)
- self.buttonReboot.grid(row=0,column=4)
master.bind_all("<Alt-r>", partial(actions.reboot,config))
+ Tooltip(self.buttonReboot, text="Reboot the computer back to the login screen")
+ self.buttonReboot.grid(row=0,column=4)
- #self.buttonCancel = tk.Button(frame, text="Cancel", underline=0, command=frame.quit)
self.buttonCancel = tk.Button(frame, text="Cancel", underline=0, command=self.quitaction)
- self.buttonCancel.grid(row=1,columnspan=8,sticky=tk.W+tk.E)
master.bind_all("<Alt-c>", self.quitaction)
+ Tooltip(self.buttonCancel, text="Do nothing; just close this window")
+ self.buttonCancel.grid(row=1,columnspan=8,sticky=tk.W+tk.E)
# Found this after trial and error.
def quitaction(self,b=None):
@@ -407,15 +348,7 @@ root = tk.Tk()
# MAIN LOOP
root.title("Log out options")
-#root.iconbitmap(r'/usr/share/icons/Numix/48/actions/system-logout.svg')
imgicon = get_scaled_icon(config.get_logout_icon(),24,config.get_icon_theme())
-#if USE_PRIVATE_TCL_IMAGES is None:
-# #imgicon = PhotoImage(file=os.path.join("/usr/share/icons/Adwaita/24x24/actions","system-log-out.png"))
-# imgicon = get_scaled_icon(config.get_logout_icon(),24)
-#else:
-# #imgicon = PhotoImage_from_png(file=os.path.join("/usr/share/icons/Adwaita/24x24/actions","system-log-out.png"))
-# imgicon = get_scaled_icon(config.get_logout_icon(),24)
-#print(imgicon)
root.tk.call('wm','iconphoto', root._w, imgicon)
app = App(root)
root.mainloop()
bgstack15