We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Runners can be configured when not yet installed, but not after removal
### Bug description

When you go into the Preferences dialog, Runners section, all the runners may be configured even if not installed. But  if you remove one, it's configure button disappears.

### How to Reproduce

Go into Preferences, select "Runners". Now, pick a runner and remove it. The configure button for that runner will disappear.

I think that is correct- but notice that all the other uninstalled runners have configure buttons. See the media attached. That can't be right.

### Expected behavior

I expect that the configure button will appear only for installed runners in the first place.

### Log output

```shell
INFO     2021-12-24 07:12:16,550 [startup.check_driver:53]:Using NVIDIA drivers 470.86 for x86_64
INFO     2021-12-24 07:12:16,550 [startup.check_driver:57]:GPU: NVIDIA GeForce RTX 3060
INFO     2021-12-24 07:12:16,550 [startup.check_driver:73]:GPU: 10DE:2503 196E:1377 (nvidia drivers)
DEBUG    2021-12-24 07:12:16,725 [lutriswindow.update_store:451]:Showing 25 games
DEBUG    2021-12-24 07:12:20,443 [application.show_window:259]:Showing window <class 'lutris.gui.config.preferences_dialog.PreferencesDialog'>{}
DEBUG    2021-12-24 07:12:26,667 [application.on_app_window_destroyed:276]:Removed window <class 'lutris.gui.config.preferences_dialog.PreferencesDialog'>{}
INFO     2021-12-24 07:12:28,505 [application.do_shutdown:631]:Shutting down Lutris

Hmm, using the master branch to repro produces less logging!
```


### System Information

```shell
[System]
OS:              Pop!_OS 21.10 impish
Arch:            x86_64
Kernel:          5.15.8-76051508-generic
Desktop:         GNOME
Display Server:  x11

[CPU]
Vendor:          AuthenticAMD
Model:           AMD Ryzen 7 5800X 8-Core Processor
Physical cores:  8
Logical cores:   16

[Memory]
RAM:             31.4 GB
Swap:            0.0 GB

[Graphics]
Vendor:          NVIDIA Corporation
OpenGL Renderer: NVIDIA GeForce RTX 3060/PCIe/SSE2
OpenGL Version:  4.6.0 NVIDIA 470.86
OpenGL Core:     4.6.0 NVIDIA 470.86
OpenGL ES:       OpenGL ES 3.2 NVIDIA 470.86
Vulkan:          Supported
```


### Media (optional)

![Screenshot from 2021-12-24 07-06-15](https://user-images.githubusercontent.com/6507403/147351426-da379253-2415-47bf-8ca3-711c33b63236.png)


### Checklist:

- [X] I'm not asking for support with a game or the wine runner.
- [X] I have followed the above mentioned guides and have all the graphics and wine dependencies installed.
- [X] I have checked for existing issues that describe my problem prior to opening this one.
- [X] I understand that improperly formatted bug reports may be closed without explanation.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lutris/gui/config/runner_box.py`
Content:
```
1 from gettext import gettext as _
2 
3 from gi.repository import GObject, Gtk
4 
5 from lutris import runners
6 from lutris.gui.config.runner import RunnerConfigDialog
7 from lutris.gui.dialogs import ErrorDialog, QuestionDialog
8 from lutris.gui.dialogs.download import simple_downloader
9 from lutris.gui.dialogs.runner_install import RunnerInstallDialog
10 from lutris.gui.widgets.utils import ICON_SIZE, get_icon
11 from lutris.util.log import logger
12 
13 
14 class RunnerBox(Gtk.Box):
15     __gsignals__ = {
16         "runner-installed": (GObject.SIGNAL_RUN_FIRST, None, ()),
17         "runner-removed": (GObject.SIGNAL_RUN_FIRST, None, ()),
18     }
19 
20     def __init__(self, runner_name):
21         super().__init__(visible=True)
22 
23         self.connect("runner-installed", self.on_runner_installed)
24         self.connect("runner-removed", self.on_runner_removed)
25 
26         self.set_margin_bottom(12)
27         self.set_margin_top(12)
28         self.set_margin_left(12)
29         self.set_margin_right(12)
30         self.runner = runners.import_runner(runner_name)()
31         icon = get_icon(self.runner.name, icon_format='pixbuf', size=ICON_SIZE)
32         if icon:
33             runner_icon = Gtk.Image(visible=True)
34             runner_icon.set_from_pixbuf(icon)
35         else:
36             runner_icon = Gtk.Image.new_from_icon_name("package-x-generic-symbolic", Gtk.IconSize.DND)
37             runner_icon.show()
38         runner_icon.set_margin_right(12)
39         self.pack_start(runner_icon, False, True, 6)
40 
41         self.runner_label_box = Gtk.VBox(visible=True)
42         self.runner_label_box.set_margin_top(12)
43 
44         runner_label = Gtk.Label(visible=True)
45         runner_label.set_alignment(0, 0.5)
46         runner_label.set_markup("<b>%s</b>" % self.runner.human_name)
47         self.runner_label_box.pack_start(runner_label, False, False, 0)
48 
49         desc_label = Gtk.Label(visible=True)
50         desc_label.set_alignment(0, 0.5)
51         desc_label.set_text(self.runner.description)
52         self.runner_label_box.pack_start(desc_label, False, False, 0)
53 
54         self.pack_start(self.runner_label_box, True, True, 0)
55 
56         self.configure_button = Gtk.Button.new_from_icon_name("preferences-system-symbolic", Gtk.IconSize.BUTTON)
57         self.configure_button.set_margin_right(12)
58         self.configure_button.connect("clicked", self.on_configure_clicked)
59         self.configure_button.show()
60         self.pack_start(self.configure_button, False, False, 0)
61         if not self.runner.is_installed():
62             self.runner_label_box.set_sensitive(False)
63         self.action_alignment = Gtk.Alignment.new(0.5, 0.5, 0, 0)
64         self.action_alignment.show()
65         self.action_alignment.add(self.get_action_button())
66         self.pack_start(self.action_alignment, False, False, 0)
67 
68     def get_action_button(self):
69         """Return a install or remove button"""
70         if self.runner.multiple_versions:
71             _button = Gtk.Button.new_from_icon_name("preferences-other-symbolic", Gtk.IconSize.BUTTON)
72             _button.get_style_context().add_class("circular")
73             _button.connect("clicked", self.on_versions_clicked)
74         else:
75             if self.runner.is_installed():
76                 _button = Gtk.Button.new_from_icon_name("edit-delete-symbolic", Gtk.IconSize.BUTTON)
77                 _button.get_style_context().add_class("circular")
78                 _button.connect("clicked", self.on_remove_clicked)
79             else:
80                 _button = Gtk.Button.new_from_icon_name("system-software-install-symbolic", Gtk.IconSize.BUTTON)
81                 _button.get_style_context().add_class("circular")
82                 _button.connect("clicked", self.on_install_clicked)
83         _button.show()
84         return _button
85 
86     def on_versions_clicked(self, widget):
87         RunnerInstallDialog(
88             _("Manage %s versions") % self.runner.name,
89             None,
90             self.runner.name
91         )
92         # connect a runner-installed signal from the above dialog?
93 
94     def on_install_clicked(self, widget):
95         """Install a runner."""
96         logger.debug("Install of %s requested", self.runner)
97         try:
98             self.runner.install(downloader=simple_downloader)
99         except (
100             runners.RunnerInstallationError,
101             runners.NonInstallableRunnerError,
102         ) as ex:
103             logger.error(ex)
104             ErrorDialog(ex.message)
105             return
106         if self.runner.is_installed():
107             self.emit("runner-installed")
108         else:
109             logger.error("Runner failed to install")
110 
111     def on_configure_clicked(self, widget):
112         RunnerConfigDialog(self.runner)
113 
114     def on_remove_clicked(self, widget):
115         dialog = QuestionDialog(
116             {
117                 "title": _("Do you want to uninstall %s?") % self.runner.human_name,
118                 "question": _("This will remove <b>%s</b> and all associated data." % self.runner.human_name)
119 
120             }
121         )
122         if Gtk.ResponseType.YES == dialog.result:
123             self.runner.uninstall()
124             self.emit("runner-removed")
125 
126     def on_runner_installed(self, widget):
127         """Called after the runnner is installed"""
128         self.runner_label_box.set_sensitive(True)
129         self.configure_button.show()
130         self.action_alignment.get_children()[0].destroy()
131         self.action_alignment.add(self.get_action_button())
132 
133     def on_runner_removed(self, widget):
134         """Called after the runner is removed"""
135         self.runner_label_box.set_sensitive(False)
136         self.configure_button.hide()
137         self.action_alignment.get_children()[0].destroy()
138         self.action_alignment.add(self.get_action_button())
139
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lutris/gui/config/runner_box.py b/lutris/gui/config/runner_box.py
--- a/lutris/gui/config/runner_box.py
+++ b/lutris/gui/config/runner_box.py
@@ -126,13 +126,11 @@
     def on_runner_installed(self, widget):
         """Called after the runnner is installed"""
         self.runner_label_box.set_sensitive(True)
-        self.configure_button.show()
         self.action_alignment.get_children()[0].destroy()
         self.action_alignment.add(self.get_action_button())
 
     def on_runner_removed(self, widget):
         """Called after the runner is removed"""
         self.runner_label_box.set_sensitive(False)
-        self.configure_button.hide()
         self.action_alignment.get_children()[0].destroy()
         self.action_alignment.add(self.get_action_button())

{"golden_diff": "diff --git a/lutris/gui/config/runner_box.py b/lutris/gui/config/runner_box.py\n--- a/lutris/gui/config/runner_box.py\n+++ b/lutris/gui/config/runner_box.py\n@@ -126,13 +126,11 @@\n     def on_runner_installed(self, widget):\n         \"\"\"Called after the runnner is installed\"\"\"\n         self.runner_label_box.set_sensitive(True)\n-        self.configure_button.show()\n         self.action_alignment.get_children()[0].destroy()\n         self.action_alignment.add(self.get_action_button())\n \n     def on_runner_removed(self, widget):\n         \"\"\"Called after the runner is removed\"\"\"\n         self.runner_label_box.set_sensitive(False)\n-        self.configure_button.hide()\n         self.action_alignment.get_children()[0].destroy()\n         self.action_alignment.add(self.get_action_button())\n", "issue": "Runners can be configured when not yet installed, but not after removal\n### Bug description\n\nWhen you go into the Preferences dialog, Runners section, all the runners may be configured even if not installed. But  if you remove one, it's configure button disappears.\n\n### How to Reproduce\n\nGo into Preferences, select \"Runners\". Now, pick a runner and remove it. The configure button for that runner will disappear.\r\n\r\nI think that is correct- but notice that all the other uninstalled runners have configure buttons. See the media attached. That can't be right.\n\n### Expected behavior\n\nI expect that the configure button will appear only for installed runners in the first place.\n\n### Log output\n\n```shell\nINFO     2021-12-24 07:12:16,550 [startup.check_driver:53]:Using NVIDIA drivers 470.86 for x86_64\r\nINFO     2021-12-24 07:12:16,550 [startup.check_driver:57]:GPU: NVIDIA GeForce RTX 3060\r\nINFO     2021-12-24 07:12:16,550 [startup.check_driver:73]:GPU: 10DE:2503 196E:1377 (nvidia drivers)\r\nDEBUG    2021-12-24 07:12:16,725 [lutriswindow.update_store:451]:Showing 25 games\r\nDEBUG    2021-12-24 07:12:20,443 [application.show_window:259]:Showing window <class 'lutris.gui.config.preferences_dialog.PreferencesDialog'>{}\r\nDEBUG    2021-12-24 07:12:26,667 [application.on_app_window_destroyed:276]:Removed window <class 'lutris.gui.config.preferences_dialog.PreferencesDialog'>{}\r\nINFO     2021-12-24 07:12:28,505 [application.do_shutdown:631]:Shutting down Lutris\r\n\r\nHmm, using the master branch to repro produces less logging!\n```\n\n\n### System Information\n\n```shell\n[System]\r\nOS:              Pop!_OS 21.10 impish\r\nArch:            x86_64\r\nKernel:          5.15.8-76051508-generic\r\nDesktop:         GNOME\r\nDisplay Server:  x11\r\n\r\n[CPU]\r\nVendor:          AuthenticAMD\r\nModel:           AMD Ryzen 7 5800X 8-Core Processor\r\nPhysical cores:  8\r\nLogical cores:   16\r\n\r\n[Memory]\r\nRAM:             31.4 GB\r\nSwap:            0.0 GB\r\n\r\n[Graphics]\r\nVendor:          NVIDIA Corporation\r\nOpenGL Renderer: NVIDIA GeForce RTX 3060/PCIe/SSE2\r\nOpenGL Version:  4.6.0 NVIDIA 470.86\r\nOpenGL Core:     4.6.0 NVIDIA 470.86\r\nOpenGL ES:       OpenGL ES 3.2 NVIDIA 470.86\r\nVulkan:          Supported\n```\n\n\n### Media (optional)\n\n![Screenshot from 2021-12-24 07-06-15](https://user-images.githubusercontent.com/6507403/147351426-da379253-2415-47bf-8ca3-711c33b63236.png)\r\n\n\n### Checklist:\n\n- [X] I'm not asking for support with a game or the wine runner.\n- [X] I have followed the above mentioned guides and have all the graphics and wine dependencies installed.\n- [X] I have checked for existing issues that describe my problem prior to opening this one.\n- [X] I understand that improperly formatted bug reports may be closed without explanation.\n", "before_files": [{"content": "from gettext import gettext as _\n\nfrom gi.repository import GObject, Gtk\n\nfrom lutris import runners\nfrom lutris.gui.config.runner import RunnerConfigDialog\nfrom lutris.gui.dialogs import ErrorDialog, QuestionDialog\nfrom lutris.gui.dialogs.download import simple_downloader\nfrom lutris.gui.dialogs.runner_install import RunnerInstallDialog\nfrom lutris.gui.widgets.utils import ICON_SIZE, get_icon\nfrom lutris.util.log import logger\n\n\nclass RunnerBox(Gtk.Box):\n    __gsignals__ = {\n        \"runner-installed\": (GObject.SIGNAL_RUN_FIRST, None, ()),\n        \"runner-removed\": (GObject.SIGNAL_RUN_FIRST, None, ()),\n    }\n\n    def __init__(self, runner_name):\n        super().__init__(visible=True)\n\n        self.connect(\"runner-installed\", self.on_runner_installed)\n        self.connect(\"runner-removed\", self.on_runner_removed)\n\n        self.set_margin_bottom(12)\n        self.set_margin_top(12)\n        self.set_margin_left(12)\n        self.set_margin_right(12)\n        self.runner = runners.import_runner(runner_name)()\n        icon = get_icon(self.runner.name, icon_format='pixbuf', size=ICON_SIZE)\n        if icon:\n            runner_icon = Gtk.Image(visible=True)\n            runner_icon.set_from_pixbuf(icon)\n        else:\n            runner_icon = Gtk.Image.new_from_icon_name(\"package-x-generic-symbolic\", Gtk.IconSize.DND)\n            runner_icon.show()\n        runner_icon.set_margin_right(12)\n        self.pack_start(runner_icon, False, True, 6)\n\n        self.runner_label_box = Gtk.VBox(visible=True)\n        self.runner_label_box.set_margin_top(12)\n\n        runner_label = Gtk.Label(visible=True)\n        runner_label.set_alignment(0, 0.5)\n        runner_label.set_markup(\"<b>%s</b>\" % self.runner.human_name)\n        self.runner_label_box.pack_start(runner_label, False, False, 0)\n\n        desc_label = Gtk.Label(visible=True)\n        desc_label.set_alignment(0, 0.5)\n        desc_label.set_text(self.runner.description)\n        self.runner_label_box.pack_start(desc_label, False, False, 0)\n\n        self.pack_start(self.runner_label_box, True, True, 0)\n\n        self.configure_button = Gtk.Button.new_from_icon_name(\"preferences-system-symbolic\", Gtk.IconSize.BUTTON)\n        self.configure_button.set_margin_right(12)\n        self.configure_button.connect(\"clicked\", self.on_configure_clicked)\n        self.configure_button.show()\n        self.pack_start(self.configure_button, False, False, 0)\n        if not self.runner.is_installed():\n            self.runner_label_box.set_sensitive(False)\n        self.action_alignment = Gtk.Alignment.new(0.5, 0.5, 0, 0)\n        self.action_alignment.show()\n        self.action_alignment.add(self.get_action_button())\n        self.pack_start(self.action_alignment, False, False, 0)\n\n    def get_action_button(self):\n        \"\"\"Return a install or remove button\"\"\"\n        if self.runner.multiple_versions:\n            _button = Gtk.Button.new_from_icon_name(\"preferences-other-symbolic\", Gtk.IconSize.BUTTON)\n            _button.get_style_context().add_class(\"circular\")\n            _button.connect(\"clicked\", self.on_versions_clicked)\n        else:\n            if self.runner.is_installed():\n                _button = Gtk.Button.new_from_icon_name(\"edit-delete-symbolic\", Gtk.IconSize.BUTTON)\n                _button.get_style_context().add_class(\"circular\")\n                _button.connect(\"clicked\", self.on_remove_clicked)\n            else:\n                _button = Gtk.Button.new_from_icon_name(\"system-software-install-symbolic\", Gtk.IconSize.BUTTON)\n                _button.get_style_context().add_class(\"circular\")\n                _button.connect(\"clicked\", self.on_install_clicked)\n        _button.show()\n        return _button\n\n    def on_versions_clicked(self, widget):\n        RunnerInstallDialog(\n            _(\"Manage %s versions\") % self.runner.name,\n            None,\n            self.runner.name\n        )\n        # connect a runner-installed signal from the above dialog?\n\n    def on_install_clicked(self, widget):\n        \"\"\"Install a runner.\"\"\"\n        logger.debug(\"Install of %s requested\", self.runner)\n        try:\n            self.runner.install(downloader=simple_downloader)\n        except (\n            runners.RunnerInstallationError,\n            runners.NonInstallableRunnerError,\n        ) as ex:\n            logger.error(ex)\n            ErrorDialog(ex.message)\n            return\n        if self.runner.is_installed():\n            self.emit(\"runner-installed\")\n        else:\n            logger.error(\"Runner failed to install\")\n\n    def on_configure_clicked(self, widget):\n        RunnerConfigDialog(self.runner)\n\n    def on_remove_clicked(self, widget):\n        dialog = QuestionDialog(\n            {\n                \"title\": _(\"Do you want to uninstall %s?\") % self.runner.human_name,\n                \"question\": _(\"This will remove <b>%s</b> and all associated data.\" % self.runner.human_name)\n\n            }\n        )\n        if Gtk.ResponseType.YES == dialog.result:\n            self.runner.uninstall()\n            self.emit(\"runner-removed\")\n\n    def on_runner_installed(self, widget):\n        \"\"\"Called after the runnner is installed\"\"\"\n        self.runner_label_box.set_sensitive(True)\n        self.configure_button.show()\n        self.action_alignment.get_children()[0].destroy()\n        self.action_alignment.add(self.get_action_button())\n\n    def on_runner_removed(self, widget):\n        \"\"\"Called after the runner is removed\"\"\"\n        self.runner_label_box.set_sensitive(False)\n        self.configure_button.hide()\n        self.action_alignment.get_children()[0].destroy()\n        self.action_alignment.add(self.get_action_button())\n", "path": "lutris/gui/config/runner_box.py"}], "after_files": [{"content": "from gettext import gettext as _\n\nfrom gi.repository import GObject, Gtk\n\nfrom lutris import runners\nfrom lutris.gui.config.runner import RunnerConfigDialog\nfrom lutris.gui.dialogs import ErrorDialog, QuestionDialog\nfrom lutris.gui.dialogs.download import simple_downloader\nfrom lutris.gui.dialogs.runner_install import RunnerInstallDialog\nfrom lutris.gui.widgets.utils import ICON_SIZE, get_icon\nfrom lutris.util.log import logger\n\n\nclass RunnerBox(Gtk.Box):\n    __gsignals__ = {\n        \"runner-installed\": (GObject.SIGNAL_RUN_FIRST, None, ()),\n        \"runner-removed\": (GObject.SIGNAL_RUN_FIRST, None, ()),\n    }\n\n    def __init__(self, runner_name):\n        super().__init__(visible=True)\n\n        self.connect(\"runner-installed\", self.on_runner_installed)\n        self.connect(\"runner-removed\", self.on_runner_removed)\n\n        self.set_margin_bottom(12)\n        self.set_margin_top(12)\n        self.set_margin_left(12)\n        self.set_margin_right(12)\n        self.runner = runners.import_runner(runner_name)()\n        icon = get_icon(self.runner.name, icon_format='pixbuf', size=ICON_SIZE)\n        if icon:\n            runner_icon = Gtk.Image(visible=True)\n            runner_icon.set_from_pixbuf(icon)\n        else:\n            runner_icon = Gtk.Image.new_from_icon_name(\"package-x-generic-symbolic\", Gtk.IconSize.DND)\n            runner_icon.show()\n        runner_icon.set_margin_right(12)\n        self.pack_start(runner_icon, False, True, 6)\n\n        self.runner_label_box = Gtk.VBox(visible=True)\n        self.runner_label_box.set_margin_top(12)\n\n        runner_label = Gtk.Label(visible=True)\n        runner_label.set_alignment(0, 0.5)\n        runner_label.set_markup(\"<b>%s</b>\" % self.runner.human_name)\n        self.runner_label_box.pack_start(runner_label, False, False, 0)\n\n        desc_label = Gtk.Label(visible=True)\n        desc_label.set_alignment(0, 0.5)\n        desc_label.set_text(self.runner.description)\n        self.runner_label_box.pack_start(desc_label, False, False, 0)\n\n        self.pack_start(self.runner_label_box, True, True, 0)\n\n        self.configure_button = Gtk.Button.new_from_icon_name(\"preferences-system-symbolic\", Gtk.IconSize.BUTTON)\n        self.configure_button.set_margin_right(12)\n        self.configure_button.connect(\"clicked\", self.on_configure_clicked)\n        self.configure_button.show()\n        self.pack_start(self.configure_button, False, False, 0)\n        if not self.runner.is_installed():\n            self.runner_label_box.set_sensitive(False)\n        self.action_alignment = Gtk.Alignment.new(0.5, 0.5, 0, 0)\n        self.action_alignment.show()\n        self.action_alignment.add(self.get_action_button())\n        self.pack_start(self.action_alignment, False, False, 0)\n\n    def get_action_button(self):\n        \"\"\"Return a install or remove button\"\"\"\n        if self.runner.multiple_versions:\n            _button = Gtk.Button.new_from_icon_name(\"preferences-other-symbolic\", Gtk.IconSize.BUTTON)\n            _button.get_style_context().add_class(\"circular\")\n            _button.connect(\"clicked\", self.on_versions_clicked)\n        else:\n            if self.runner.is_installed():\n                _button = Gtk.Button.new_from_icon_name(\"edit-delete-symbolic\", Gtk.IconSize.BUTTON)\n                _button.get_style_context().add_class(\"circular\")\n                _button.connect(\"clicked\", self.on_remove_clicked)\n            else:\n                _button = Gtk.Button.new_from_icon_name(\"system-software-install-symbolic\", Gtk.IconSize.BUTTON)\n                _button.get_style_context().add_class(\"circular\")\n                _button.connect(\"clicked\", self.on_install_clicked)\n        _button.show()\n        return _button\n\n    def on_versions_clicked(self, widget):\n        RunnerInstallDialog(\n            _(\"Manage %s versions\") % self.runner.name,\n            None,\n            self.runner.name\n        )\n        # connect a runner-installed signal from the above dialog?\n\n    def on_install_clicked(self, widget):\n        \"\"\"Install a runner.\"\"\"\n        logger.debug(\"Install of %s requested\", self.runner)\n        try:\n            self.runner.install(downloader=simple_downloader)\n        except (\n            runners.RunnerInstallationError,\n            runners.NonInstallableRunnerError,\n        ) as ex:\n            logger.error(ex)\n            ErrorDialog(ex.message)\n            return\n        if self.runner.is_installed():\n            self.emit(\"runner-installed\")\n        else:\n            logger.error(\"Runner failed to install\")\n\n    def on_configure_clicked(self, widget):\n        RunnerConfigDialog(self.runner)\n\n    def on_remove_clicked(self, widget):\n        dialog = QuestionDialog(\n            {\n                \"title\": _(\"Do you want to uninstall %s?\") % self.runner.human_name,\n                \"question\": _(\"This will remove <b>%s</b> and all associated data.\" % self.runner.human_name)\n\n            }\n        )\n        if Gtk.ResponseType.YES == dialog.result:\n            self.runner.uninstall()\n            self.emit(\"runner-removed\")\n\n    def on_runner_installed(self, widget):\n        \"\"\"Called after the runnner is installed\"\"\"\n        self.runner_label_box.set_sensitive(True)\n        self.action_alignment.get_children()[0].destroy()\n        self.action_alignment.add(self.get_action_button())\n\n    def on_runner_removed(self, widget):\n        \"\"\"Called after the runner is removed\"\"\"\n        self.runner_label_box.set_sensitive(False)\n        self.action_alignment.get_children()[0].destroy()\n        self.action_alignment.add(self.get_action_button())\n", "path": "lutris/gui/config/runner_box.py"}]}