diff --git a/CHANGELOG b/CHANGELOG index 94da1d6..f5e2e08 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +2025-01-02: [FEATURE] More methods for generating `PopupMenu` objects 2024-12-26: [BUGFIX] Fix control highlight border in popup toolkit 2024-12-23: [FEATURE] Add ability to mask icons in `StatusNotifier` widget 2024-12-11: [BREAKING CHANGE] `dbus-next` dependency has been replaced with `dbus-fast`. Update to latest qtile is also required. diff --git a/docs/manual/how_to/popup.rst b/docs/manual/how_to/popup.rst index 0930421..40b5478 100644 --- a/docs/manual/how_to/popup.rst +++ b/docs/manual/how_to/popup.rst @@ -385,5 +385,61 @@ the shutdown command. Note that the menu items can be configured individually. Configuration options for the layout (border etc.) are passed to the ``generate`` method. +Alternatively, the ``PopupMenu.make_generators`` method can be used to apply a config to menu items +and the layout. It returns three functions which are used to create menu items, separators and the layout. +For example, to recreate the text menu above with a custom theme, you could do the following: + +.. code:: python + + from libqtile.lazy import lazy + + from qtile_extras.popup import PopupMenu + + + # Define config for menu and create functions to generate menu + menu_config = { + "foreground": "0ff", + "foreground_disabled": "666", + "foreground_highlighted": "fff", + "highlight": "900", + "border_width": 2 + } + + item, separator, generate = PopupMenu.make_generators(**menu_config) + + + @lazy.function + def show_text_power_menu(qtile): + items = [ + item(text="Power Menu", enabled=False), + separator(), + item( + text="Lock", + mouse_callbacks={ + "Button1": lazy.spawn("/path/to/lock_cmd") + } + ), + item( + text="Sleep", + mouse_callbacks={ + "Button1": lazy.spawn("/path/to/lock_cmd") + } + ), + item( + text="Shutdown", + mouse_callbacks={ + "Button1": lazy.shutdown() + } + ), + ] + menu = generate(qtile, menuitems=items) + menu.show(centered=True) + + keys = [ + ... + Key([mod, "shift"], "q", show_text_power_menu) + ... + ] + Configuration options for the menu objects can be found on :ref:`the reference page `. diff --git a/docs/manual/ref/popup.rst b/docs/manual/ref/popup.rst index 1b4a4c2..a735752 100644 --- a/docs/manual/ref/popup.rst +++ b/docs/manual/ref/popup.rst @@ -44,7 +44,7 @@ These are basic text menus. The layout is generated automatically and users are required to provide the menu items. .. qtile_class:: qtile_extras.popup.menu.PopupMenu - :methods: generate,from_dbus_menu + :methods: generate,from_dbus_menu,make_generators .. qtile_class:: qtile_extras.popup.menu.PopupMenuItem diff --git a/qtile_extras/popup/menu.py b/qtile_extras/popup/menu.py index b6a6cef..58bb69b 100644 --- a/qtile_extras/popup/menu.py +++ b/qtile_extras/popup/menu.py @@ -180,6 +180,38 @@ def __init__(self, qtile, controls, **config): PopupGridLayout.__init__(self, qtile, controls=controls, **config) self.add_defaults(PopupMenu.defaults) + @staticmethod + def make_generators(qtile=None, **config): + """ + Returns three functions (``make_popupmenuitem``, ``make_popupmenuseparator`` and + ``generate_menu``) to help creation of menus with custom configs. + + ``make_popupmenuitem`` and ``make_popupmenuseparator`` create those items but with + the supplied config already applied to them. Config values can still be overriden + on an item-by-item basis. + + ``generate_menu`` creates the menu with the supplied config. + + The ``qtile`` object must be passed to either the ``make_generators`` method or the + ``generate_menu`` function. + """ + _qtile = qtile + + def make_popupmenuitem(text, **itemconfig): + cfg = {**config, **itemconfig} + return PopupMenuItem(text=text, **cfg) + + def make_popupmenuseparator(**itemconfig): + cfg = {**config, **itemconfig} + return PopupMenuSeparator(**cfg) + + def generate_menu(qtile=None, menuitems=list(), **menuconfig): + qt = _qtile or qtile + cfg = {**config, **menuconfig} + return PopupMenu.generate(qt, menuitems=menuitems, **cfg) + + return make_popupmenuitem, make_popupmenuseparator, generate_menu + @classmethod def from_dbus_menu(cls, qtile, dbusmenuitems, **config): """