We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Dialog windows are not modal
### Describe the bug

Create a dialog like this:
```
async def on_button_test(widget):
    await self.main_window.info_dialog(title="Dialog", message="An Info Dialog")
```
You can now click on the main window behind the dialog  and the main window is activated although the dialog is still floating above the window. This allows the dialog to be shown again or other actions to be triggered although the user should be blocked in the dialog.

Either change the behavior of dialogs to be modal or add a "modal={True|False}" property to "info_dialog" (and all similar functions) to enforce this.

### Steps to reproduce

1) Create self.main_window.info_dialog
2) Click main window
3) Main window is activated and can be interacted with. 

### Expected behavior

Main window can not be activated (dialog keeps focus)

### Screenshots

_No response_

### Environment

Linux (GenToo). Toga in virtual environment.

### Logs

_No response_

### Additional context

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gtk/src/toga_gtk/dialogs.py`
Content:
```
1 from abc import ABC
2 from pathlib import Path
3 
4 from .libs import Gtk
5 
6 
7 class BaseDialog(ABC):
8     def __init__(self, interface):
9         self.interface = interface
10         self.interface._impl = self
11 
12 
13 class MessageDialog(BaseDialog):
14     def __init__(
15         self,
16         interface,
17         title,
18         message_type,
19         buttons,
20         success_result=None,
21         **kwargs,
22     ):
23         super().__init__(interface=interface)
24         self.success_result = success_result
25 
26         self.native = Gtk.MessageDialog(
27             transient_for=interface.window._impl.native,
28             flags=0,
29             message_type=message_type,
30             buttons=buttons,
31             text=title,
32         )
33         self.build_dialog(**kwargs)
34 
35         self.native.connect("response", self.gtk_response)
36         self.native.show()
37 
38     def build_dialog(self, message):
39         self.native.format_secondary_text(message)
40 
41     def gtk_response(self, dialog, response):
42         if self.success_result:
43             result = response == self.success_result
44         else:
45             result = None
46 
47         self.interface.set_result(result)
48 
49         self.native.destroy()
50 
51 
52 class InfoDialog(MessageDialog):
53     def __init__(self, interface, title, message):
54         super().__init__(
55             interface=interface,
56             title=title,
57             message=message,
58             message_type=Gtk.MessageType.INFO,
59             buttons=Gtk.ButtonsType.OK,
60         )
61 
62 
63 class QuestionDialog(MessageDialog):
64     def __init__(self, interface, title, message):
65         super().__init__(
66             interface=interface,
67             title=title,
68             message=message,
69             message_type=Gtk.MessageType.QUESTION,
70             buttons=Gtk.ButtonsType.YES_NO,
71             success_result=Gtk.ResponseType.YES,
72         )
73 
74 
75 class ConfirmDialog(MessageDialog):
76     def __init__(self, interface, title, message):
77         super().__init__(
78             interface=interface,
79             title=title,
80             message=message,
81             message_type=Gtk.MessageType.WARNING,
82             buttons=Gtk.ButtonsType.OK_CANCEL,
83             success_result=Gtk.ResponseType.OK,
84         )
85 
86 
87 class ErrorDialog(MessageDialog):
88     def __init__(self, interface, title, message):
89         super().__init__(
90             interface=interface,
91             title=title,
92             message=message,
93             message_type=Gtk.MessageType.ERROR,
94             buttons=Gtk.ButtonsType.CANCEL,
95         )
96 
97 
98 class StackTraceDialog(MessageDialog):
99     def __init__(self, interface, title, **kwargs):
100         super().__init__(
101             interface=interface,
102             title=title,
103             message_type=Gtk.MessageType.ERROR,
104             buttons=(
105                 Gtk.ButtonsType.CANCEL if kwargs.get("retry") else Gtk.ButtonsType.OK
106             ),
107             success_result=Gtk.ResponseType.OK if kwargs.get("retry") else None,
108             **kwargs,
109         )
110 
111     def build_dialog(self, message, content, retry):
112         container = self.native.get_message_area()
113 
114         self.native.format_secondary_text(message)
115 
116         # Create a scrolling readonly text area, in monospace font, to contain the stack trace.
117         buffer = Gtk.TextBuffer()
118         buffer.set_text(content)
119 
120         trace = Gtk.TextView()
121         trace.set_buffer(buffer)
122         trace.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
123         trace.set_property("editable", False)
124         trace.set_property("cursor-visible", False)
125 
126         trace.get_style_context().add_class("toga")
127         trace.get_style_context().add_class("stacktrace")
128         trace.get_style_context().add_class("dialog")
129 
130         style_provider = Gtk.CssProvider()
131         style_provider.load_from_data(b".toga.stacktrace {font-family: monospace;}")
132 
133         trace.get_style_context().add_provider(
134             style_provider,
135             Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
136         )
137 
138         scroll = Gtk.ScrolledWindow()
139         scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
140         scroll.set_size_request(500, 200)
141         scroll.add(trace)
142 
143         container.pack_end(scroll, False, False, 0)
144 
145         container.show_all()
146 
147         # If this is a retry dialog, add a retry button (which maps to OK).
148         if retry:
149             self.native.add_button("Retry", Gtk.ResponseType.OK)
150 
151 
152 class FileDialog(BaseDialog):
153     def __init__(
154         self,
155         interface,
156         title,
157         filename,
158         initial_directory,
159         file_types,
160         multiple_select,
161         action,
162         ok_icon,
163     ):
164         super().__init__(interface=interface)
165 
166         self.native = Gtk.FileChooserDialog(
167             transient_for=interface.window._impl.native,
168             title=title,
169             action=action,
170         )
171         self.native.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
172         self.native.add_button(ok_icon, Gtk.ResponseType.OK)
173 
174         if filename:
175             self.native.set_current_name(filename)
176 
177         if initial_directory:
178             self.native.set_current_folder(str(initial_directory))
179 
180         if file_types:
181             for file_type in file_types:
182                 filter_filetype = Gtk.FileFilter()
183                 filter_filetype.set_name("." + file_type + " files")
184                 filter_filetype.add_pattern("*." + file_type)
185                 self.native.add_filter(filter_filetype)
186 
187         self.multiple_select = multiple_select
188         if self.multiple_select:
189             self.native.set_select_multiple(True)
190 
191         self.native.connect("response", self.gtk_response)
192         self.native.show()
193 
194     # Provided as a stub that can be mocked in test conditions
195     def selected_path(self):
196         return self.native.get_filename()
197 
198     # Provided as a stub that can be mocked in test conditions
199     def selected_paths(self):
200         return self.native.get_filenames()
201 
202     def gtk_response(self, dialog, response):
203         if response == Gtk.ResponseType.OK:
204             if self.multiple_select:
205                 result = [Path(filename) for filename in self.selected_paths()]
206             else:
207                 result = Path(self.selected_path())
208         else:
209             result = None
210 
211         self.interface.set_result(result)
212 
213         self.native.destroy()
214 
215 
216 class SaveFileDialog(FileDialog):
217     def __init__(
218         self,
219         interface,
220         title,
221         filename,
222         initial_directory,
223         file_types=None,
224     ):
225         super().__init__(
226             interface=interface,
227             title=title,
228             filename=filename,
229             initial_directory=initial_directory,
230             file_types=file_types,
231             multiple_select=False,
232             action=Gtk.FileChooserAction.SAVE,
233             ok_icon=Gtk.STOCK_SAVE,
234         )
235 
236 
237 class OpenFileDialog(FileDialog):
238     def __init__(
239         self,
240         interface,
241         title,
242         initial_directory,
243         file_types,
244         multiple_select,
245     ):
246         super().__init__(
247             interface=interface,
248             title=title,
249             filename=None,
250             initial_directory=initial_directory,
251             file_types=file_types,
252             multiple_select=multiple_select,
253             action=Gtk.FileChooserAction.OPEN,
254             ok_icon=Gtk.STOCK_OPEN,
255         )
256 
257 
258 class SelectFolderDialog(FileDialog):
259     def __init__(
260         self,
261         interface,
262         title,
263         initial_directory,
264         multiple_select,
265     ):
266         super().__init__(
267             interface=interface,
268             title=title,
269             filename=None,
270             initial_directory=initial_directory,
271             file_types=None,
272             multiple_select=multiple_select,
273             action=Gtk.FileChooserAction.SELECT_FOLDER,
274             ok_icon=Gtk.STOCK_OPEN,
275         )
276
```
--- 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/gtk/src/toga_gtk/dialogs.py b/gtk/src/toga_gtk/dialogs.py
--- a/gtk/src/toga_gtk/dialogs.py
+++ b/gtk/src/toga_gtk/dialogs.py
@@ -30,6 +30,7 @@
             buttons=buttons,
             text=title,
         )
+        self.native.set_modal(True)
         self.build_dialog(**kwargs)
 
         self.native.connect("response", self.gtk_response)

{"golden_diff": "diff --git a/gtk/src/toga_gtk/dialogs.py b/gtk/src/toga_gtk/dialogs.py\n--- a/gtk/src/toga_gtk/dialogs.py\n+++ b/gtk/src/toga_gtk/dialogs.py\n@@ -30,6 +30,7 @@\n             buttons=buttons,\n             text=title,\n         )\n+        self.native.set_modal(True)\n         self.build_dialog(**kwargs)\n \n         self.native.connect(\"response\", self.gtk_response)\n", "issue": "Dialog windows are not modal\n### Describe the bug\n\nCreate a dialog like this:\r\n```\r\nasync def on_button_test(widget):\r\n    await self.main_window.info_dialog(title=\"Dialog\", message=\"An Info Dialog\")\r\n```\r\nYou can now click on the main window behind the dialog  and the main window is activated although the dialog is still floating above the window. This allows the dialog to be shown again or other actions to be triggered although the user should be blocked in the dialog.\r\n\r\nEither change the behavior of dialogs to be modal or add a \"modal={True|False}\" property to \"info_dialog\" (and all similar functions) to enforce this.\n\n### Steps to reproduce\n\n1) Create self.main_window.info_dialog\r\n2) Click main window\r\n3) Main window is activated and can be interacted with. \n\n### Expected behavior\n\nMain window can not be activated (dialog keeps focus)\n\n### Screenshots\n\n_No response_\n\n### Environment\n\nLinux (GenToo). Toga in virtual environment.\n\n### Logs\n\n_No response_\n\n### Additional context\n\n_No response_\n", "before_files": [{"content": "from abc import ABC\nfrom pathlib import Path\n\nfrom .libs import Gtk\n\n\nclass BaseDialog(ABC):\n    def __init__(self, interface):\n        self.interface = interface\n        self.interface._impl = self\n\n\nclass MessageDialog(BaseDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        message_type,\n        buttons,\n        success_result=None,\n        **kwargs,\n    ):\n        super().__init__(interface=interface)\n        self.success_result = success_result\n\n        self.native = Gtk.MessageDialog(\n            transient_for=interface.window._impl.native,\n            flags=0,\n            message_type=message_type,\n            buttons=buttons,\n            text=title,\n        )\n        self.build_dialog(**kwargs)\n\n        self.native.connect(\"response\", self.gtk_response)\n        self.native.show()\n\n    def build_dialog(self, message):\n        self.native.format_secondary_text(message)\n\n    def gtk_response(self, dialog, response):\n        if self.success_result:\n            result = response == self.success_result\n        else:\n            result = None\n\n        self.interface.set_result(result)\n\n        self.native.destroy()\n\n\nclass InfoDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.INFO,\n            buttons=Gtk.ButtonsType.OK,\n        )\n\n\nclass QuestionDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.QUESTION,\n            buttons=Gtk.ButtonsType.YES_NO,\n            success_result=Gtk.ResponseType.YES,\n        )\n\n\nclass ConfirmDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.WARNING,\n            buttons=Gtk.ButtonsType.OK_CANCEL,\n            success_result=Gtk.ResponseType.OK,\n        )\n\n\nclass ErrorDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.ERROR,\n            buttons=Gtk.ButtonsType.CANCEL,\n        )\n\n\nclass StackTraceDialog(MessageDialog):\n    def __init__(self, interface, title, **kwargs):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message_type=Gtk.MessageType.ERROR,\n            buttons=(\n                Gtk.ButtonsType.CANCEL if kwargs.get(\"retry\") else Gtk.ButtonsType.OK\n            ),\n            success_result=Gtk.ResponseType.OK if kwargs.get(\"retry\") else None,\n            **kwargs,\n        )\n\n    def build_dialog(self, message, content, retry):\n        container = self.native.get_message_area()\n\n        self.native.format_secondary_text(message)\n\n        # Create a scrolling readonly text area, in monospace font, to contain the stack trace.\n        buffer = Gtk.TextBuffer()\n        buffer.set_text(content)\n\n        trace = Gtk.TextView()\n        trace.set_buffer(buffer)\n        trace.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)\n        trace.set_property(\"editable\", False)\n        trace.set_property(\"cursor-visible\", False)\n\n        trace.get_style_context().add_class(\"toga\")\n        trace.get_style_context().add_class(\"stacktrace\")\n        trace.get_style_context().add_class(\"dialog\")\n\n        style_provider = Gtk.CssProvider()\n        style_provider.load_from_data(b\".toga.stacktrace {font-family: monospace;}\")\n\n        trace.get_style_context().add_provider(\n            style_provider,\n            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,\n        )\n\n        scroll = Gtk.ScrolledWindow()\n        scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)\n        scroll.set_size_request(500, 200)\n        scroll.add(trace)\n\n        container.pack_end(scroll, False, False, 0)\n\n        container.show_all()\n\n        # If this is a retry dialog, add a retry button (which maps to OK).\n        if retry:\n            self.native.add_button(\"Retry\", Gtk.ResponseType.OK)\n\n\nclass FileDialog(BaseDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        filename,\n        initial_directory,\n        file_types,\n        multiple_select,\n        action,\n        ok_icon,\n    ):\n        super().__init__(interface=interface)\n\n        self.native = Gtk.FileChooserDialog(\n            transient_for=interface.window._impl.native,\n            title=title,\n            action=action,\n        )\n        self.native.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)\n        self.native.add_button(ok_icon, Gtk.ResponseType.OK)\n\n        if filename:\n            self.native.set_current_name(filename)\n\n        if initial_directory:\n            self.native.set_current_folder(str(initial_directory))\n\n        if file_types:\n            for file_type in file_types:\n                filter_filetype = Gtk.FileFilter()\n                filter_filetype.set_name(\".\" + file_type + \" files\")\n                filter_filetype.add_pattern(\"*.\" + file_type)\n                self.native.add_filter(filter_filetype)\n\n        self.multiple_select = multiple_select\n        if self.multiple_select:\n            self.native.set_select_multiple(True)\n\n        self.native.connect(\"response\", self.gtk_response)\n        self.native.show()\n\n    # Provided as a stub that can be mocked in test conditions\n    def selected_path(self):\n        return self.native.get_filename()\n\n    # Provided as a stub that can be mocked in test conditions\n    def selected_paths(self):\n        return self.native.get_filenames()\n\n    def gtk_response(self, dialog, response):\n        if response == Gtk.ResponseType.OK:\n            if self.multiple_select:\n                result = [Path(filename) for filename in self.selected_paths()]\n            else:\n                result = Path(self.selected_path())\n        else:\n            result = None\n\n        self.interface.set_result(result)\n\n        self.native.destroy()\n\n\nclass SaveFileDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        filename,\n        initial_directory,\n        file_types=None,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=filename,\n            initial_directory=initial_directory,\n            file_types=file_types,\n            multiple_select=False,\n            action=Gtk.FileChooserAction.SAVE,\n            ok_icon=Gtk.STOCK_SAVE,\n        )\n\n\nclass OpenFileDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        initial_directory,\n        file_types,\n        multiple_select,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=None,\n            initial_directory=initial_directory,\n            file_types=file_types,\n            multiple_select=multiple_select,\n            action=Gtk.FileChooserAction.OPEN,\n            ok_icon=Gtk.STOCK_OPEN,\n        )\n\n\nclass SelectFolderDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        initial_directory,\n        multiple_select,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=None,\n            initial_directory=initial_directory,\n            file_types=None,\n            multiple_select=multiple_select,\n            action=Gtk.FileChooserAction.SELECT_FOLDER,\n            ok_icon=Gtk.STOCK_OPEN,\n        )\n", "path": "gtk/src/toga_gtk/dialogs.py"}], "after_files": [{"content": "from abc import ABC\nfrom pathlib import Path\n\nfrom .libs import Gtk\n\n\nclass BaseDialog(ABC):\n    def __init__(self, interface):\n        self.interface = interface\n        self.interface._impl = self\n\n\nclass MessageDialog(BaseDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        message_type,\n        buttons,\n        success_result=None,\n        **kwargs,\n    ):\n        super().__init__(interface=interface)\n        self.success_result = success_result\n\n        self.native = Gtk.MessageDialog(\n            transient_for=interface.window._impl.native,\n            flags=0,\n            message_type=message_type,\n            buttons=buttons,\n            text=title,\n        )\n        self.native.set_modal(True)\n        self.build_dialog(**kwargs)\n\n        self.native.connect(\"response\", self.gtk_response)\n        self.native.show()\n\n    def build_dialog(self, message):\n        self.native.format_secondary_text(message)\n\n    def gtk_response(self, dialog, response):\n        if self.success_result:\n            result = response == self.success_result\n        else:\n            result = None\n\n        self.interface.set_result(result)\n\n        self.native.destroy()\n\n\nclass InfoDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.INFO,\n            buttons=Gtk.ButtonsType.OK,\n        )\n\n\nclass QuestionDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.QUESTION,\n            buttons=Gtk.ButtonsType.YES_NO,\n            success_result=Gtk.ResponseType.YES,\n        )\n\n\nclass ConfirmDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.WARNING,\n            buttons=Gtk.ButtonsType.OK_CANCEL,\n            success_result=Gtk.ResponseType.OK,\n        )\n\n\nclass ErrorDialog(MessageDialog):\n    def __init__(self, interface, title, message):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message=message,\n            message_type=Gtk.MessageType.ERROR,\n            buttons=Gtk.ButtonsType.CANCEL,\n        )\n\n\nclass StackTraceDialog(MessageDialog):\n    def __init__(self, interface, title, **kwargs):\n        super().__init__(\n            interface=interface,\n            title=title,\n            message_type=Gtk.MessageType.ERROR,\n            buttons=(\n                Gtk.ButtonsType.CANCEL if kwargs.get(\"retry\") else Gtk.ButtonsType.OK\n            ),\n            success_result=Gtk.ResponseType.OK if kwargs.get(\"retry\") else None,\n            **kwargs,\n        )\n\n    def build_dialog(self, message, content, retry):\n        container = self.native.get_message_area()\n\n        self.native.format_secondary_text(message)\n\n        # Create a scrolling readonly text area, in monospace font, to contain the stack trace.\n        buffer = Gtk.TextBuffer()\n        buffer.set_text(content)\n\n        trace = Gtk.TextView()\n        trace.set_buffer(buffer)\n        trace.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)\n        trace.set_property(\"editable\", False)\n        trace.set_property(\"cursor-visible\", False)\n\n        trace.get_style_context().add_class(\"toga\")\n        trace.get_style_context().add_class(\"stacktrace\")\n        trace.get_style_context().add_class(\"dialog\")\n\n        style_provider = Gtk.CssProvider()\n        style_provider.load_from_data(b\".toga.stacktrace {font-family: monospace;}\")\n\n        trace.get_style_context().add_provider(\n            style_provider,\n            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,\n        )\n\n        scroll = Gtk.ScrolledWindow()\n        scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)\n        scroll.set_size_request(500, 200)\n        scroll.add(trace)\n\n        container.pack_end(scroll, False, False, 0)\n\n        container.show_all()\n\n        # If this is a retry dialog, add a retry button (which maps to OK).\n        if retry:\n            self.native.add_button(\"Retry\", Gtk.ResponseType.OK)\n\n\nclass FileDialog(BaseDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        filename,\n        initial_directory,\n        file_types,\n        multiple_select,\n        action,\n        ok_icon,\n    ):\n        super().__init__(interface=interface)\n\n        self.native = Gtk.FileChooserDialog(\n            transient_for=interface.window._impl.native,\n            title=title,\n            action=action,\n        )\n        self.native.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)\n        self.native.add_button(ok_icon, Gtk.ResponseType.OK)\n\n        if filename:\n            self.native.set_current_name(filename)\n\n        if initial_directory:\n            self.native.set_current_folder(str(initial_directory))\n\n        if file_types:\n            for file_type in file_types:\n                filter_filetype = Gtk.FileFilter()\n                filter_filetype.set_name(\".\" + file_type + \" files\")\n                filter_filetype.add_pattern(\"*.\" + file_type)\n                self.native.add_filter(filter_filetype)\n\n        self.multiple_select = multiple_select\n        if self.multiple_select:\n            self.native.set_select_multiple(True)\n\n        self.native.connect(\"response\", self.gtk_response)\n        self.native.show()\n\n    # Provided as a stub that can be mocked in test conditions\n    def selected_path(self):\n        return self.native.get_filename()\n\n    # Provided as a stub that can be mocked in test conditions\n    def selected_paths(self):\n        return self.native.get_filenames()\n\n    def gtk_response(self, dialog, response):\n        if response == Gtk.ResponseType.OK:\n            if self.multiple_select:\n                result = [Path(filename) for filename in self.selected_paths()]\n            else:\n                result = Path(self.selected_path())\n        else:\n            result = None\n\n        self.interface.set_result(result)\n\n        self.native.destroy()\n\n\nclass SaveFileDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        filename,\n        initial_directory,\n        file_types=None,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=filename,\n            initial_directory=initial_directory,\n            file_types=file_types,\n            multiple_select=False,\n            action=Gtk.FileChooserAction.SAVE,\n            ok_icon=Gtk.STOCK_SAVE,\n        )\n\n\nclass OpenFileDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        initial_directory,\n        file_types,\n        multiple_select,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=None,\n            initial_directory=initial_directory,\n            file_types=file_types,\n            multiple_select=multiple_select,\n            action=Gtk.FileChooserAction.OPEN,\n            ok_icon=Gtk.STOCK_OPEN,\n        )\n\n\nclass SelectFolderDialog(FileDialog):\n    def __init__(\n        self,\n        interface,\n        title,\n        initial_directory,\n        multiple_select,\n    ):\n        super().__init__(\n            interface=interface,\n            title=title,\n            filename=None,\n            initial_directory=initial_directory,\n            file_types=None,\n            multiple_select=multiple_select,\n            action=Gtk.FileChooserAction.SELECT_FOLDER,\n            ok_icon=Gtk.STOCK_OPEN,\n        )\n", "path": "gtk/src/toga_gtk/dialogs.py"}]}