The menu categories can now be expanded and collapsed without using shift, so just right arrow to expand and left arrow to collapse.

This commit is contained in:
Storm Dragon 2024-06-29 20:49:18 -04:00
parent c0b5c2ee29
commit 05cd390554

View File

@ -19,21 +19,21 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk from gi.repository import Gtk, Gdk
def read_desktop_files(paths): def read_desktop_files(paths):
desktop_entries = [] desktopEntries = []
for path in paths: for path in paths:
for file in Path(path).rglob('*.desktop'): for file in Path(path).rglob('*.desktop'):
config = configparser.ConfigParser(interpolation=None) config = configparser.ConfigParser(interpolation=None)
config.read(file) config.read(file)
desktop_entries.append(config) desktopEntries.append(config)
return desktop_entries return desktopEntries
user_applications_path = Path.home() / '.local/share/applications' userApplicationsPath = Path.home() / '.local/share/applications'
system_applications_path = Path('/usr/share/applications') systemApplicationsPath = Path('/usr/share/applications')
desktop_entries = read_desktop_files([user_applications_path, system_applications_path]) desktopEntries = read_desktop_files([userApplicationsPath, systemApplicationsPath])
# Combine some of the categories # Combine some of the categories
category_map = { categoryMap = {
"2DGraphics": "Office", "2DGraphics": "Office",
"Accessibility": "Settings", "Accessibility": "Settings",
"Audio": "Audio and Video", "Audio": "Audio and Video",
@ -85,16 +85,16 @@ category_map = {
} }
categories = defaultdict(set) categories = defaultdict(set)
for entry in desktop_entries: for entry in desktopEntries:
try: try:
entry_categories = entry.get('Desktop Entry', 'Categories').split(';') entryCategories = entry.get('Desktop Entry', 'Categories').split(';')
for category in entry_categories: for category in entryCategories:
combined_category = category_map.get(category, category) combinedCategory = categoryMap.get(category, category)
name = entry.get('Desktop Entry', 'Name') name = entry.get('Desktop Entry', 'Name')
exec_command = entry.get('Desktop Entry', 'Exec') execCommand = entry.get('Desktop Entry', 'Exec')
# Use a tuple of name and exec_command as a unique identifier # Use a tuple of name and execCommand as a unique identifier
if (name, exec_command) not in categories[combined_category]: if (name, execCommand) not in categories[combinedCategory]:
categories[combined_category].add((name, exec_command)) categories[combinedCategory].add((name, execCommand))
except configparser.NoOptionError: except configparser.NoOptionError:
continue continue
@ -106,15 +106,15 @@ class Xdg_Menu_Window(Gtk.Window):
self.store = Gtk.TreeStore(str, str) # Columns: Category/Application Name, Exec Command self.store = Gtk.TreeStore(str, str) # Columns: Category/Application Name, Exec Command
sorted_categories = sorted(categories.items()) # Sort categories alphabetically sortedCategories = sorted(categories.items()) # Sort categories alphabetically
for category, entries in sorted_categories: for category, entries in sortedCategories:
if category == "": if category == "":
continue continue
category_iter = self.store.append(parent=None, row=[category, None]) categoryIter = self.store.append(parent=None, row=[category, None])
sorted_entries = sorted(entries, key=lambda e: e[0]) # Sort entries by name sortedEntries = sorted(entries, key=lambda e: e[0]) # Sort entries by name
for name, exec_command in sorted_entries: for name, execCommand in sortedEntries:
self.store.append(parent=category_iter, row=[name, exec_command]) self.store.append(parent=categoryIter, row=[name, execCommand])
self.treeview = Gtk.TreeView(model=self.store) self.treeview = Gtk.TreeView(model=self.store)
renderer = Gtk.CellRendererText() renderer = Gtk.CellRendererText()
@ -135,9 +135,9 @@ class Xdg_Menu_Window(Gtk.Window):
def on_row_activated(self, treeview, path, column): def on_row_activated(self, treeview, path, column):
model = treeview.get_model() model = treeview.get_model()
iter = model.get_iter(path) iter = model.get_iter(path)
exec_command = model.get_value(iter, 1) execCommand = model.get_value(iter, 1)
if exec_command: if execCommand:
os.system(exec_command) os.system(execCommand)
def on_focus_out(self, widget, event): def on_focus_out(self, widget, event):
Gtk.main_quit() Gtk.main_quit()
@ -147,7 +147,7 @@ class Xdg_Menu_Window(Gtk.Window):
state = event.state state = event.state
if keyval == Gdk.KEY_Escape: if keyval == Gdk.KEY_Escape:
Gtk.main_quit() Gtk.main_quit()
elif state & Gdk.ModifierType.SHIFT_MASK and keyval == Gdk.KEY_Left: elif keyval == Gdk.KEY_Left:
path = self.treeview.get_cursor()[0] path = self.treeview.get_cursor()[0]
if path: if path:
iter = self.store.get_iter(path) iter = self.store.get_iter(path)
@ -160,6 +160,11 @@ class Xdg_Menu_Window(Gtk.Window):
self.treeview.collapse_row(parent_path) self.treeview.collapse_row(parent_path)
else: else:
self.treeview.collapse_row(path) self.treeview.collapse_row(path)
elif keyval == Gdk.KEY_Right:
path = self.treeview.get_cursor()[0]
if path:
if not self.treeview.row_expanded(path):
self.treeview.expand_row(path, open_all=False)
win = Xdg_Menu_Window() win = Xdg_Menu_Window()
win.connect("destroy", Gtk.main_quit) win.connect("destroy", Gtk.main_quit)