diff options
-rwxr-xr-x | logout-manager-tcl.py | 116 |
1 files changed, 104 insertions, 12 deletions
diff --git a/logout-manager-tcl.py b/logout-manager-tcl.py index c605dc0..b9d9997 100755 --- a/logout-manager-tcl.py +++ b/logout-manager-tcl.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 # Startdate: 2019-06-12 20:05 +# Dependencies: +# python36-tkinter | python3-tk +# python36-pillow-tk | python3-pil.imagetk # WORKHERE: # add icons # add full headers @@ -12,12 +15,18 @@ # alternate for passing params https://stackoverflow.com/questions/6920302/how-to-pass-arguments-to-a-button-command-in-tkinter # https://stackoverflow.com/questions/18537918/set-window-icon#18538416 # the exact syntax <Alt-k> for master.bind https://stackoverflow.com/questions/16082243/how-to-bind-ctrl-in-python-tkinter +# https://pillow.readthedocs.io/en/stable/reference/ImageTk.html +# gtk-3.0 default icon theme https://coderwall.com/p/no3qfa/setting-gtk2-and-gtk3-theme-via-config-file +# homedir https://stackoverflow.com/questions/4028904/how-to-get-the-home-directory-in-python +# natural sort https://stackoverflow.com/questions/46228101/sort-list-of-strings-by-two-substrings-using-lambda-function/46228199#46228199 -import os, sys -sys.path.append("/home/bgirton/dev/logout-manager") -import lmlib +import os, sys, configparser, glob, re from tkinter import * from functools import partial +from pathlib import Path +from PIL import Image, ImageTk +sys.path.append("/home/bgirton/dev/logout-manager") +import lmlib config = lmlib.Initialize_config() actions = lmlib.Actions @@ -25,13 +34,89 @@ actions = lmlib.Actions # graphical classes and functions print("Loading graphics...") -def icon_bitmap(name = "", theme = "default", size = "48"): - # WORKHERE: can build some tool that loops through the icon theme dirs +def get_gtk3_default_theme(): + # abstracted so it does not clutter get_scaled_icon + name = None + gtk3_config_path = os.path.join(os.path.expanduser("~"),".config","gtk-3.0","settings.ini") + gtk3_config = configparser.ConfigParser() + gtk3_config.read(gtk3_config_path) + try: + if 'Settings' in gtk3_config: + name = gtk3_config['Settings']['gtk-icon-theme-name'] + elif 'settings' in gtk3_config: + name = gtk3_config['settings']['gtk-icon-theme-name'] + except: + # supposed failsafe + name = "hicolor" + return name + +def tryint(s): + try: + return int(s) + except: + 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])] + 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"): + # return the complicated numerical value for the weird size options + if type == "all": + return int(re.split("[^0-9]+",x)[0]) * 100 + int( re.split("[^0-9]+",x)[1] if len(re.split("[^0-9]+",x)) >= 2 else 0 ) + else: + return int(re.split("[^0-9]+",x)[0]) + +def find_best_size_match(size, thelist): + # return item from sorted thelist whose split("/")[5] is the first to meet or exceed the requested size + return next(( i for i in thelist if mynum(i.split("/")[5],"real") >= size ), thelist[-1]) + +def get_filename_of_icon(name, theme = "hicolor", size = 48, category = "actions"): + # poor man's attempt at walking through fd.o icon theme + filename = None + # example: Adwaita system-log-out + + # first, find all files underneath /usr/share/icons/$THEME/$SIZE + print("Finding filename of icon.") + results = glob.glob("/usr/share/icons/"+theme+"/*/"+category+"/"+name+".*") + # the sort arranges it so a Numix/24 dir comes before a Numix/24@2x dir + results = sorted(results, key=sort_sizes) + #print(results) + # now find the first one that matches + filename = find_best_size_match(size,results) + return filename + +def get_scaled_icon(icon_name, size = 24, fallback_icon_name = "", icon_theme = "default"): + iconfilename = None + # if name is a specific filename, just use it. - # if the only thing that is found during the looping is a svg, return None - # if the valid file provided is svg, then try a few derivations to get a png, else return None - imgicon = PhotoImage(file=os.path.join("/usr/share/icons/Adwaita/24x24/actions","system-log-out.png")) - return imgicon + if Path(icon_name).is_file(): + #print("This is a file:",icon_name) + iconfilename = icon_name + else: + + if icon_theme == "default": + # retrieve default theme from config file + #print("Discovering default icon theme...") + icon_theme = get_gtk3_default_theme() + # so now that icon_theme is defined, let us go find the icon that matches the requested name and size, in the actions category + #print("Using icon theme",icon_theme) + iconfilename = get_filename_of_icon(name=icon_name, theme=icon_theme, size=size) + + # So now that we think we have derived the correct filename... + try: + print("Trying icon file",iconfilename) + photo = Image.open(iconfilename) + except: + print("Error with icon file.") + return None + # If I ever add HiDPI stuff, multiple size here by the factor. So, size * 1.25 + photo.thumbnail(size=[size, size]) + photo2 = ImageTk.PhotoImage(photo) + return photo2 class App: def __init__(self, master): @@ -39,15 +124,22 @@ class App: frame.grid(row=0) self.buttonLock = Button(frame, text="Lock", underline=3, command=partial(actions.lock,config)) - #self.buttonLock.pack(side=LEFT) 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) master.bind_all("<Alt-k>", partial(actions.lock,config)) - self.buttonLogout = Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config)) - self.buttonLogout.grid(row=0,column=1) + # WORKS, for basic image loading. + #self.photoLogout = get_scaled_icon("/usr/share/icons/Adwaita/48x48/actions/system-log-out.png") + #self.buttonLogout = 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") + self.buttonLogout = Button(frame, text="Logout", underline=0, command=lambda: actions.logout(config), image=self.photoLogout, compound=LEFT) master.bind_all("<Alt-l>", partial(actions.logout,config)) + self.buttonLogout.grid(row=0,column=1) self.buttonHibernate = Button(frame, text="Hibernate", underline=0, command=lambda: actions.hibernate(config)) self.buttonHibernate.grid(row=0,column=2) |