Repository: qtile/qtile

Issue:
`GroupBox` widget ignores `fmt`
Setting the `fmt` kwarg in `GroupBox` to anything does not affect the widget in any way. Since it's not really a normal widget in terms of what it displays this somewhat makes sense, though I think it'd be better if `fmt` was applied to each of the groups that is displayed.


Discussion:
Interesting question.

`fmt` is only shown as a configuration option for `GroupBox` because it inherits from `base._TextBox`. However, from what I can tell, the widget is not using any of the functionality from `base._TextBox`, hence why this is ignored.

There are two options here:

1. Stop inheriting from `_TextBox`. This would remove the `fmt` option from the docs which should reduce confusion.
2. Format the box label in accordance with `fmt`.

Given that the widget displays the group's label (not its name), I'm inclined to go with option 1 as it should be possible to format the groups' labels when they're being created without the need for additional formatting.
Or perhaps just don't use `_TextBox.__init__`?:

```diff
diff --git a/libqtile/widget/groupbox.py b/libqtile/widget/groupbox.py
index 2a754d4d..85559d48 100644
--- a/libqtile/widget/groupbox.py
+++ b/libqtile/widget/groupbox.py
@@ -45,7 +45,9 @@ class _GroupBase(base._TextBox, base.PaddingMixin, 
base.MarginMixin):
     ] # type: List[Tuple[str, Any, str]]

     def __init__(self, **config):
- base._TextBox.__init__(self, width=bar.CALCULATED, **config)
+ _Widget.__init__(self, width=bar.CALCULATED, **config)
+ self.layout = None
+ self._text = ""
         self.add_defaults(_GroupBase.defaults)
         self.add_defaults(base.PaddingMixin.defaults)
         self.add_defaults(base.MarginMixin.defaults)
```

On Mon, Jan 10 2022 at 08:50:08 -0800, elParaguayo 
***@***.***> wrote:
> Interesting question.
> 
> fmt is only shown as a configuration option for GroupBox because it 
> inherits from base._TextBox. However, from what I can tell, the 
> widget is not using any of the functionality from base._TextBox, 
> hence why this is ignored.
> 
> There are two options here:
> 
> Stop inheriting from _TextBox. This would remove the fmt option from 
> the docs which should reduce confusion. Format the box label in 
> accordance with fmt.
> Given that the widget displays the group's label (not its name), I'm 
> inclined to go with option 1 as it should be possible to format the 
> groups' labels when they're being created without the need for 
> additional formatting.
> 
> —
> Reply to this email directly, view it on GitHub, or unsubscribe.
> Triage notifications on the go with GitHub Mobile for iOS or Android.
> You are receiving this because you are subscribed to this 
> thread.Message ID: ***@***.***>
> 



That's the point. It uses `base._TextBox.__init__` but `base._Widget._configure` so why not inherit from `base._Widget` instead?

Also, the docs populate the `defaults` table by combining the `defaults` in each inherited class.  The `__init__` method doesn't impact this.
I think it'd be better to go with option 2 (formatting the labels with `fmt`) to allow using pango markdown for formatting in the labels.
The `fmt` attribute doesn't determine whether pango markdown is allowed or not. That's a separate option that's set when creating a text layout. You can still enable pango markdown with option 1.
Well yeah you can enable markdown but you can't use it if you have no way to set the format string. Unless there's another way to use the markdown I'm not aware of? But on other widgets I generally just do something like `fmt="<b>{}</b>"`.
Markdown just applies on the text string so you can add formatting directly to it without using `fmt`. e.g. you could do
``` python
groups = [Group(i, label=f"<b>{i}</b>") for i in "123456789"]
```
Huh that doesn't work for me. Instead it just explicitly shows the `<b>` and `</b>` tags. 

In general pango markdown only works for me when I include it in `fmt`. For example in `WindowName` if I set `format="<b>{state}{name}</b>"` then it will display the tags verbatim, but if I use `fmt=<b>{}</b>` instead it works fine. I assume this is on purpose and any markdown characters get escaped so that if a markdown sequence is somehow included in a window title it doesn't cause formatting.
Groupbox does not have markdown enabled (you can't toggle it as an option - it's currently hard coded) so using tags won't work at the moment.

My point was that that has nothing to do with using `fmt` here. 

You are right about the escaping of text, though. I think text is typically escaped before passing through `fmt`. Including the tags in the string would also much up the widget size.

I see your point. Maybe it's easier `fmt` here so at least we're consistent.
Ah ok makes sense.
Sorry. Also edited my post as you were replying. See my additions.
> That's the point. It uses base._TextBox.__init__ but base._Widget._configure so why not inherit from base._Widget instead?

But doesn't it also use methods that are inherited from _TextBox?
Don't think so. Text is set directly in the `drawbox` method and doesn't use the `text` setter from `_TextBox`. No formatting is applied.

Resolving patch:
diff --git a/libqtile/widget/groupbox.py b/libqtile/widget/groupbox.py
--- a/libqtile/widget/groupbox.py
+++ b/libqtile/widget/groupbox.py
@@ -52,7 +52,7 @@ def __init__(self, **config):
 
     def box_width(self, groups):
         width, _ = self.drawer.max_layout_size(
-            [i.label for i in groups], self.font, self.fontsize
+            [self.fmt.format(i.label) for i in groups], self.font, self.fontsize
         )
         return width + self.padding_x * 2 + self.borderwidth * 2
 
@@ -93,7 +93,7 @@ def drawbox(
         line=False,
         highlighted=False,
     ):
-        self.layout.text = text
+        self.layout.text = self.fmt.format(text)
         self.layout.font_family = self.font
         self.layout.font_size = self.fontsize
         self.layout.colour = textcolor


Test patch: