By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

file-listing: implement this nightmare

roundabout,
created on Sunday, 7 December 2025, 13:18:04 (1765113484), received on Sunday, 7 December 2025, 13:18:07 (1765113487)
Author identity: Vlad <vlad.muntoiu@gmail.com>

93253fe1af0ba87766494372fa38c2d45ce53c55

applets/file-listing/__init__.py

@@ -0,0 +1,237 @@

                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Nesting file menu applet for the Panorama panel.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Copyright 2025, roundabout-host.com <vlad@roundabout-host.com>
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        This program is free software: you can redistribute it and/or modify
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        it under the terms of the GNU General Public Licence as published by
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        the Free Software Foundation, either version 3 of the Licence, 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 Licence for more details.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        You should have received a copy of the GNU General Public Licence
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        along with this program. If not, see <https://www.gnu.org/licenses/>.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import hashlib
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import os
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import locale
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pathlib import Path
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import panorama_panel
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import gi
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        gi.require_version("Gtk", "4.0")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from gi.repository import Gtk, GLib, Gio, Gdk, GObject
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        module_directory = Path(__file__).resolve().parent
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        locale.bindtextdomain("panorama-panel-file-listing", module_directory / "locale")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        _ = lambda x: locale.dgettext("panorama-panel-file-listing", x)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class FileMenuAttributeIter(Gio.MenuAttributeIter, GObject.Object):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, attributes: dict, **kwargs):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                GObject.Object.__init__(self, **kwargs)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._attributes: dict = attributes
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._values = list(attributes.items())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._i = 0
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_next(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if self._i >= len(self._values):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return False, None, None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return True, *self._values[self._i]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class FileMenuLinkIter(Gio.MenuLinkIter, GObject.Object):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, attributes: dict, **kwargs):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                GObject.Object.__init__(self, **kwargs)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._attributes: dict = attributes
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._values = list(attributes.items())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self._i = 0
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_next(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if self._i >= len(self._values):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return False, None, None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return True, *self._values[self._i]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class FileMenu(Gio.MenuModel, GObject.Object):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, root: Path, storage: dict[str, GObject.Object], new_action_callback, prune_action_callback, **kwargs):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                GObject.Object.__init__(self, **kwargs)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.root: Path = root
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.links: dict[str, Gio.MenuModel] = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.files: list[Path] = []
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.storage = storage
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.callback = new_action_callback
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.callback_prune = prune_action_callback
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.enabled = False
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_is_mutable(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return True
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_n_items(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if not self.enabled:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return 0
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.files = list(self.root.iterdir())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return len(self.files)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_item_attribute_value(self, item_index, attribute, expected_type = None):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                match attribute:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    case Gio.MENU_ATTRIBUTE_ACTION:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return GLib.Variant("s", "applet.open")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    case Gio.MENU_ATTRIBUTE_TARGET:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return GLib.Variant("s", str(file.resolve()))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    case Gio.MENU_ATTRIBUTE_LABEL:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return GLib.Variant("s", file.name.replace("_", "_"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    case "submenu-action":
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return GLib.Variant("s", f"applet.submenu-status-{hashlib.md5(str(file).encode()).hexdigest()}")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    case _:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        return None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def make_submenu(self, name):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action_id = hashlib.md5(str(self.root / name).encode())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if name not in self.links:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    menu = FileMenu(self.root / name, self.storage, self.callback, self.callback_prune)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    container = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    options_section = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    open_directory = Gio.MenuItem()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    open_directory.set_label(_("Open directory"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    open_directory.set_action_and_target_value("applet.open", GLib.Variant("s", str((self.root / name).resolve())))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    options_section.append_item(open_directory)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    container.append_section(None, options_section)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    container.append_section(None, menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    container.file_list = menu
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.links[name] = container
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.storage[action_id.hexdigest()] = menu
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.callback(action_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_item_link(self, item_index, link):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if file.is_dir() and link == Gio.MENU_LINK_SUBMENU:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.make_submenu(file.name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return self.links[file.name]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_iterate_item_attributes(self, item_index):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return FileMenuAttributeIter(
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            Gio.MENU_ATTRIBUTE_ACTION: GLib.Variant("s", "applet.open"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            Gio.MENU_ATTRIBUTE_TARGET: GLib.Variant("s", str(file.resolve())),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            Gio.MENU_ATTRIBUTE_LABEL: GLib.Variant("s", file.name.replace("_", "_")),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                            "submenu-action": GLib.Variant("s", f"applet.submenu-status-{hashlib.md5(str(file).encode()).hexdigest()}"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                )
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_iterate_item_links(self, item_index):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if file.is_dir():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.make_submenu(file.name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return FileMenuLinkIter({Gio.MENU_LINK_SUBMENU: self.links[file.name]})
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return FileMenuLinkIter({})
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_item_attributes(self, item_index):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return {
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        Gio.MENU_ATTRIBUTE_ACTION: GLib.Variant("s", "applet.open"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        Gio.MENU_ATTRIBUTE_TARGET: GLib.Variant("s", str(file.resolve())),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        Gio.MENU_ATTRIBUTE_LABEL: GLib.Variant("s", file.name.replace("_", "_")),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        "submenu-action": GLib.Variant("s", f"applet.submenu-status-{hashlib.md5(str(file).encode()).hexdigest()}"),
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                }
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def do_get_item_links(self, item_index):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                file = self.files[item_index]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if file.is_dir():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.make_submenu(file.name)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return {Gio.MENU_LINK_SUBMENU: self.links[file.name]}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def generate(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.enabled = True
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.items_changed(0, 0, self.get_n_items())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def prune(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.enabled = False
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for file in self.files:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    if file.is_dir():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        action_id = hashlib.md5(str(self.root / file.name).encode())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        self.links[file.name].file_list.prune()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        del self.storage[action_id.hexdigest()]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                        self.callback_prune(action_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.items_changed(0, len(self.files), 0)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.files.clear()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.links.clear()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class FileListingApplet(panorama_panel.Applet):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            name = _("File listing")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            description = _("View a nesting menu of your files")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                super().__init__(orientation=orientation, config=config)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if config is None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    config = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.action_group = Gio.SimpleActionGroup()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.directory = Path(config.get("directory", "~")).expanduser().resolve()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button = Gtk.MenuButton()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_has_frame(False)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.append(self.button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_always_show_arrow(True)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover = Gtk.PopoverMenu(flags=Gtk.PopoverMenuFlags.NESTED, has_arrow=False)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.actions = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.container_menu = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.options_section = Gio.Menu()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                open_directory = Gio.MenuItem()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                open_directory.set_label(_("Open directory"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                open_directory.set_action_and_target_value("applet.open", GLib.Variant("s", str(self.directory)))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.options_section.append_item(open_directory)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.container_menu.append_section(None, self.options_section)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.menu = FileMenu(self.directory, self.actions, self.new_action, self.delete_action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.container_menu.append_section(None, self.menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.container_menu.file_list = self.menu
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.set_menu_model(self.menu)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_popover(self.popover)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.open_action = Gio.SimpleAction(name="open", parameter_type=GLib.VariantType("s"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.open_action.connect("activate", self.open_file)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.submenu_action = Gio.SimpleAction(name="submenu-status", state=GLib.Variant("b", False))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.submenu_action.connect("notify", self.submenu_changed)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.action_group.add_action(self.open_action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.action_group.add_action(self.submenu_action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.insert_action_group("applet", self.action_group)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.connect("realize", lambda *args: self.menu.generate())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.connect("unrealize", lambda *args: self.menu.prune())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def new_action(self, action_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action = Gio.SimpleAction(name=f"submenu-status-{action_id.hexdigest()}", state=GLib.Variant("b", False))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action.submenu = self.actions[action_id.hexdigest()]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                action.connect("notify", self.submenu_changed)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.action_group.add_action(action)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def delete_action(self, action_id):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.action_group.remove(f"submenu-status-{action_id.hexdigest()}")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def open_file(self, action, data: GLib.Variant):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                Gio.AppInfo.launch_default_for_uri(GLib.filename_to_uri(data.get_string()))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def submenu_changed(self, action, parameter):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if action.get_state():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    action.submenu.generate()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                else:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    action.submenu.prune()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def get_config(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return {"directory": str(self.directory)}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def set_panel_position(self, position):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_direction(panorama_panel.POSITION_TO_ARROW[panorama_panel.OPPOSITE_POSITION[position]])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

config.yaml

@@ -93,4 +93,6 @@ panels:

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    show_only_this_wf_workspace: true
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    show_only_this_output: true
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                centre: []
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            right: []
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            right:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            - FileListingApplet:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                directory: /home/vlad