We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Using escape key permanently hides preferences window
## 🐛 Bug
Related to #2527 ... but perhaps different enough for a different issue:

If you use the escape key when the preferences window is open, it will indeed close the window.  However, using command-W or File > Preferences will not re-show the window.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `napari/_qt/dialogs/preferences_dialog.py`
Content:
```
1 import json
2 
3 from qtpy.QtCore import QSize, Signal
4 from qtpy.QtWidgets import (
5     QDialog,
6     QHBoxLayout,
7     QLabel,
8     QListWidget,
9     QPushButton,
10     QStackedWidget,
11     QVBoxLayout,
12     QWidget,
13 )
14 
15 from ..._vendor.qt_json_builder.qt_jsonschema_form import WidgetBuilder
16 from ...utils.settings import SETTINGS
17 from ...utils.translations import trans
18 
19 
20 class PreferencesDialog(QDialog):
21     """Preferences Dialog for Napari user settings."""
22 
23     ui_schema = {
24         "call_order": {"ui:widget": "plugins"},
25     }
26 
27     resized = Signal(QSize)
28     closed = Signal()
29 
30     def __init__(self, parent=None):
31         super().__init__(parent)
32 
33         self._list = QListWidget(self)
34         self._stack = QStackedWidget(self)
35 
36         self._list.setObjectName("Preferences")
37 
38         # Set up buttons
39         self._button_cancel = QPushButton(trans._("Cancel"))
40         self._button_ok = QPushButton(trans._("OK"))
41         self._default_restore = QPushButton(trans._("Restore defaults"))
42 
43         # Setup
44         self.setWindowTitle(trans._("Preferences"))
45 
46         # Layout
47         left_layout = QVBoxLayout()
48         left_layout.addWidget(self._list)
49         left_layout.addStretch()
50         left_layout.addWidget(self._default_restore)
51         left_layout.addWidget(self._button_cancel)
52         left_layout.addWidget(self._button_ok)
53 
54         main_layout = QHBoxLayout()
55         main_layout.addLayout(left_layout, 1)
56         main_layout.addWidget(self._stack, 3)
57 
58         self.setLayout(main_layout)
59 
60         # Signals
61 
62         self._list.currentRowChanged.connect(
63             lambda index: self._stack.setCurrentIndex(index)
64         )
65         self._button_cancel.clicked.connect(self.on_click_cancel)
66         self._button_ok.clicked.connect(self.on_click_ok)
67         self._default_restore.clicked.connect(self.restore_defaults)
68 
69         # Make widget
70 
71         self.make_dialog()
72         self._list.setCurrentRow(0)
73 
74     def closeEvent(self, event):
75         """Override to emit signal."""
76         self.closed.emit()
77         super().closeEvent(event)
78 
79     def resizeEvent(self, event):
80         """Override to emit signal."""
81         self.resized.emit(event.size())
82         super().resizeEvent(event)
83 
84     def make_dialog(self):
85         """Removes settings not to be exposed to user and creates dialog pages."""
86 
87         # Because there are multiple pages, need to keep a dictionary of values dicts.
88         # One set of keywords are for each page, then in each entry for a page, there are dicts
89         # of setting and its value.
90 
91         self._values_orig_dict = {}
92         self._values_dict = {}
93         self._setting_changed_dict = {}
94 
95         for page, setting in SETTINGS.schemas().items():
96             schema, values, properties = self.get_page_dict(setting)
97 
98             self._setting_changed_dict[page] = {}
99             self._values_orig_dict[page] = values
100             self._values_dict[page] = values
101 
102             # Only add pages if there are any properties to add.
103             if properties:
104                 self.add_page(schema, values)
105 
106     def get_page_dict(self, setting):
107         """Provides the schema, set of values for each setting, and the properties
108         for each setting.
109 
110         Parameters
111         ----------
112         setting : dict
113             Dictionary of settings for a page within the settings manager.
114 
115         Returns
116         -------
117         schema : dict
118             Json schema of the setting page.
119         values : dict
120             Dictionary of values currently set for each parameter in the settings.
121         properties : dict
122             Dictionary of properties within the json schema.
123 
124         """
125 
126         schema = json.loads(setting['json_schema'])
127         # Need to remove certain properties that will not be displayed on the GUI
128         properties = schema.pop('properties')
129         model = setting['model']
130         values = model.dict()
131         napari_config = getattr(model, "NapariConfig", None)
132         if napari_config is not None:
133             for val in napari_config.preferences_exclude:
134                 properties.pop(val)
135                 values.pop(val)
136 
137         schema['properties'] = properties
138 
139         return schema, values, properties
140 
141     def restore_defaults(self):
142         """Launches dialog to confirm restore settings choice."""
143 
144         widget = ConfirmDialog(
145             parent=self,
146             text=trans._("Are you sure you want to restore default settings?"),
147         )
148         widget.valueChanged.connect(self._reset_widgets)
149         widget.exec_()
150 
151     def _reset_widgets(self):
152         """Deletes the widgets and rebuilds with defaults."""
153         self.close()
154         self._list.clear()
155 
156         for n in range(self._stack.count()):
157             widget = self._stack.removeWidget(self._stack.currentWidget())
158             del widget
159 
160         self.make_dialog()
161         self._list.setCurrentRow(0)
162         self.show()
163 
164     def on_click_ok(self):
165         """Keeps the selected preferences saved to SETTINGS."""
166         self.close()
167 
168     def on_click_cancel(self):
169         """Restores the settings in place when dialog was launched."""
170         # Need to check differences for each page.
171         for n in range(self._stack.count()):
172             # Must set the current row so that the proper list is updated
173             # in check differences.
174             self._list.setCurrentRow(n)
175             page = self._list.currentItem().text().split(" ")[0].lower()
176             # get new values for settings.  If they were changed from values at beginning
177             # of preference dialog session, change them back.
178             # Using the settings value seems to be the best way to get the checkboxes right
179             # on the plugin call order widget.
180             setting = SETTINGS.schemas()[page]
181             schema, new_values, properties = self.get_page_dict(setting)
182             self.check_differences(self._values_orig_dict[page], new_values)
183 
184         self._list.setCurrentRow(0)
185         self.close()
186 
187     def add_page(self, schema, values):
188         """Creates a new page for each section in dialog.
189 
190         Parameters
191         ----------
192         schema : dict
193             Json schema including all information to build each page in the
194             preferences dialog.
195         values : dict
196             Dictionary of current values set in preferences.
197         """
198         widget = self.build_page_dialog(schema, values)
199         self._list.addItem(schema["title"])
200         self._stack.addWidget(widget)
201 
202     def build_page_dialog(self, schema, values):
203         """Builds the preferences widget using the json schema builder.
204 
205         Parameters
206         ----------
207         schema : dict
208             Json schema including all information to build each page in the
209             preferences dialog.
210         values : dict
211             Dictionary of current values set in preferences.
212         """
213 
214         builder = WidgetBuilder()
215         form = builder.create_form(schema, self.ui_schema)
216         # set state values for widget
217         form.widget.state = values
218         form.widget.on_changed.connect(
219             lambda d: self.check_differences(
220                 d,
221                 self._values_dict[schema["title"].lower()],
222             )
223         )
224 
225         return form
226 
227     def _values_changed(self, page, new_dict, old_dict):
228         """Loops through each setting in a page to determine if it changed.
229 
230         Parameters
231         ----------
232         new_dict : dict
233             Dict that has the most recent changes by user. Each key is a setting value
234             and each item is the value.
235         old_dict : dict
236             Dict wtih values set at the begining of preferences dialog session.
237 
238         """
239         for setting_name, value in new_dict.items():
240             if value != old_dict[setting_name]:
241                 self._setting_changed_dict[page][setting_name] = value
242             elif (
243                 value == old_dict[setting_name]
244                 and setting_name in self._setting_changed_dict[page]
245             ):
246                 self._setting_changed_dict[page].pop(setting_name)
247 
248     def check_differences(self, new_dict, old_dict):
249         """Changes settings in settings manager with changes from dialog.
250 
251         Parameters
252         ----------
253         new_dict : dict
254             Dict that has the most recent changes by user. Each key is a setting parameter
255             and each item is the value.
256         old_dict : dict
257             Dict wtih values set at the beginning of the preferences dialog session.
258         """
259         page = self._list.currentItem().text().split(" ")[0].lower()
260         self._values_changed(page, new_dict, old_dict)
261         different_values = self._setting_changed_dict[page]
262 
263         if len(different_values) > 0:
264             # change the values in SETTINGS
265             for setting_name, value in different_values.items():
266                 try:
267                     setattr(SETTINGS._settings[page], setting_name, value)
268                     self._values_dict[page] = new_dict
269                 except:  # noqa: E722
270                     continue
271 
272 
273 class ConfirmDialog(QDialog):
274     """Dialog to confirms a user's choice to restore default settings."""
275 
276     valueChanged = Signal(bool)
277 
278     def __init__(
279         self,
280         parent: QWidget = None,
281         text: str = "",
282     ):
283         super().__init__(parent)
284 
285         # Set up components
286         self._question = QLabel(self)
287         self._button_restore = QPushButton(trans._("Restore"))
288         self._button_cancel = QPushButton(trans._("Cancel"))
289 
290         # Widget set up
291         self._question.setText(text)
292 
293         # Layout
294         button_layout = QHBoxLayout()
295         button_layout.addWidget(self._button_cancel)
296         button_layout.addWidget(self._button_restore)
297 
298         main_layout = QVBoxLayout()
299         main_layout.addWidget(self._question)
300         main_layout.addLayout(button_layout)
301 
302         self.setLayout(main_layout)
303 
304         # Signals
305         self._button_cancel.clicked.connect(self.on_click_cancel)
306         self._button_restore.clicked.connect(self.on_click_restore)
307 
308     def on_click_cancel(self):
309         """Do not restore defaults and close window."""
310         self.close()
311 
312     def on_click_restore(self):
313         """Restore defaults and close window."""
314         SETTINGS.reset()
315         self.valueChanged.emit(True)
316         self.close()
317
```
--- 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/napari/_qt/dialogs/preferences_dialog.py b/napari/_qt/dialogs/preferences_dialog.py
--- a/napari/_qt/dialogs/preferences_dialog.py
+++ b/napari/_qt/dialogs/preferences_dialog.py
@@ -76,6 +76,11 @@
         self.closed.emit()
         super().closeEvent(event)
 
+    def reject(self):
+        """Override to handle Escape."""
+        super().reject()
+        self.close()
+
     def resizeEvent(self, event):
         """Override to emit signal."""
         self.resized.emit(event.size())

{"golden_diff": "diff --git a/napari/_qt/dialogs/preferences_dialog.py b/napari/_qt/dialogs/preferences_dialog.py\n--- a/napari/_qt/dialogs/preferences_dialog.py\n+++ b/napari/_qt/dialogs/preferences_dialog.py\n@@ -76,6 +76,11 @@\n         self.closed.emit()\n         super().closeEvent(event)\n \n+    def reject(self):\n+        \"\"\"Override to handle Escape.\"\"\"\n+        super().reject()\n+        self.close()\n+\n     def resizeEvent(self, event):\n         \"\"\"Override to emit signal.\"\"\"\n         self.resized.emit(event.size())\n", "issue": "Using escape key permanently hides preferences window\n## \ud83d\udc1b Bug\r\nRelated to #2527 ... but perhaps different enough for a different issue:\r\n\r\nIf you use the escape key when the preferences window is open, it will indeed close the window.  However, using command-W or File > Preferences will not re-show the window.\n", "before_files": [{"content": "import json\n\nfrom qtpy.QtCore import QSize, Signal\nfrom qtpy.QtWidgets import (\n    QDialog,\n    QHBoxLayout,\n    QLabel,\n    QListWidget,\n    QPushButton,\n    QStackedWidget,\n    QVBoxLayout,\n    QWidget,\n)\n\nfrom ..._vendor.qt_json_builder.qt_jsonschema_form import WidgetBuilder\nfrom ...utils.settings import SETTINGS\nfrom ...utils.translations import trans\n\n\nclass PreferencesDialog(QDialog):\n    \"\"\"Preferences Dialog for Napari user settings.\"\"\"\n\n    ui_schema = {\n        \"call_order\": {\"ui:widget\": \"plugins\"},\n    }\n\n    resized = Signal(QSize)\n    closed = Signal()\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n\n        self._list = QListWidget(self)\n        self._stack = QStackedWidget(self)\n\n        self._list.setObjectName(\"Preferences\")\n\n        # Set up buttons\n        self._button_cancel = QPushButton(trans._(\"Cancel\"))\n        self._button_ok = QPushButton(trans._(\"OK\"))\n        self._default_restore = QPushButton(trans._(\"Restore defaults\"))\n\n        # Setup\n        self.setWindowTitle(trans._(\"Preferences\"))\n\n        # Layout\n        left_layout = QVBoxLayout()\n        left_layout.addWidget(self._list)\n        left_layout.addStretch()\n        left_layout.addWidget(self._default_restore)\n        left_layout.addWidget(self._button_cancel)\n        left_layout.addWidget(self._button_ok)\n\n        main_layout = QHBoxLayout()\n        main_layout.addLayout(left_layout, 1)\n        main_layout.addWidget(self._stack, 3)\n\n        self.setLayout(main_layout)\n\n        # Signals\n\n        self._list.currentRowChanged.connect(\n            lambda index: self._stack.setCurrentIndex(index)\n        )\n        self._button_cancel.clicked.connect(self.on_click_cancel)\n        self._button_ok.clicked.connect(self.on_click_ok)\n        self._default_restore.clicked.connect(self.restore_defaults)\n\n        # Make widget\n\n        self.make_dialog()\n        self._list.setCurrentRow(0)\n\n    def closeEvent(self, event):\n        \"\"\"Override to emit signal.\"\"\"\n        self.closed.emit()\n        super().closeEvent(event)\n\n    def resizeEvent(self, event):\n        \"\"\"Override to emit signal.\"\"\"\n        self.resized.emit(event.size())\n        super().resizeEvent(event)\n\n    def make_dialog(self):\n        \"\"\"Removes settings not to be exposed to user and creates dialog pages.\"\"\"\n\n        # Because there are multiple pages, need to keep a dictionary of values dicts.\n        # One set of keywords are for each page, then in each entry for a page, there are dicts\n        # of setting and its value.\n\n        self._values_orig_dict = {}\n        self._values_dict = {}\n        self._setting_changed_dict = {}\n\n        for page, setting in SETTINGS.schemas().items():\n            schema, values, properties = self.get_page_dict(setting)\n\n            self._setting_changed_dict[page] = {}\n            self._values_orig_dict[page] = values\n            self._values_dict[page] = values\n\n            # Only add pages if there are any properties to add.\n            if properties:\n                self.add_page(schema, values)\n\n    def get_page_dict(self, setting):\n        \"\"\"Provides the schema, set of values for each setting, and the properties\n        for each setting.\n\n        Parameters\n        ----------\n        setting : dict\n            Dictionary of settings for a page within the settings manager.\n\n        Returns\n        -------\n        schema : dict\n            Json schema of the setting page.\n        values : dict\n            Dictionary of values currently set for each parameter in the settings.\n        properties : dict\n            Dictionary of properties within the json schema.\n\n        \"\"\"\n\n        schema = json.loads(setting['json_schema'])\n        # Need to remove certain properties that will not be displayed on the GUI\n        properties = schema.pop('properties')\n        model = setting['model']\n        values = model.dict()\n        napari_config = getattr(model, \"NapariConfig\", None)\n        if napari_config is not None:\n            for val in napari_config.preferences_exclude:\n                properties.pop(val)\n                values.pop(val)\n\n        schema['properties'] = properties\n\n        return schema, values, properties\n\n    def restore_defaults(self):\n        \"\"\"Launches dialog to confirm restore settings choice.\"\"\"\n\n        widget = ConfirmDialog(\n            parent=self,\n            text=trans._(\"Are you sure you want to restore default settings?\"),\n        )\n        widget.valueChanged.connect(self._reset_widgets)\n        widget.exec_()\n\n    def _reset_widgets(self):\n        \"\"\"Deletes the widgets and rebuilds with defaults.\"\"\"\n        self.close()\n        self._list.clear()\n\n        for n in range(self._stack.count()):\n            widget = self._stack.removeWidget(self._stack.currentWidget())\n            del widget\n\n        self.make_dialog()\n        self._list.setCurrentRow(0)\n        self.show()\n\n    def on_click_ok(self):\n        \"\"\"Keeps the selected preferences saved to SETTINGS.\"\"\"\n        self.close()\n\n    def on_click_cancel(self):\n        \"\"\"Restores the settings in place when dialog was launched.\"\"\"\n        # Need to check differences for each page.\n        for n in range(self._stack.count()):\n            # Must set the current row so that the proper list is updated\n            # in check differences.\n            self._list.setCurrentRow(n)\n            page = self._list.currentItem().text().split(\" \")[0].lower()\n            # get new values for settings.  If they were changed from values at beginning\n            # of preference dialog session, change them back.\n            # Using the settings value seems to be the best way to get the checkboxes right\n            # on the plugin call order widget.\n            setting = SETTINGS.schemas()[page]\n            schema, new_values, properties = self.get_page_dict(setting)\n            self.check_differences(self._values_orig_dict[page], new_values)\n\n        self._list.setCurrentRow(0)\n        self.close()\n\n    def add_page(self, schema, values):\n        \"\"\"Creates a new page for each section in dialog.\n\n        Parameters\n        ----------\n        schema : dict\n            Json schema including all information to build each page in the\n            preferences dialog.\n        values : dict\n            Dictionary of current values set in preferences.\n        \"\"\"\n        widget = self.build_page_dialog(schema, values)\n        self._list.addItem(schema[\"title\"])\n        self._stack.addWidget(widget)\n\n    def build_page_dialog(self, schema, values):\n        \"\"\"Builds the preferences widget using the json schema builder.\n\n        Parameters\n        ----------\n        schema : dict\n            Json schema including all information to build each page in the\n            preferences dialog.\n        values : dict\n            Dictionary of current values set in preferences.\n        \"\"\"\n\n        builder = WidgetBuilder()\n        form = builder.create_form(schema, self.ui_schema)\n        # set state values for widget\n        form.widget.state = values\n        form.widget.on_changed.connect(\n            lambda d: self.check_differences(\n                d,\n                self._values_dict[schema[\"title\"].lower()],\n            )\n        )\n\n        return form\n\n    def _values_changed(self, page, new_dict, old_dict):\n        \"\"\"Loops through each setting in a page to determine if it changed.\n\n        Parameters\n        ----------\n        new_dict : dict\n            Dict that has the most recent changes by user. Each key is a setting value\n            and each item is the value.\n        old_dict : dict\n            Dict wtih values set at the begining of preferences dialog session.\n\n        \"\"\"\n        for setting_name, value in new_dict.items():\n            if value != old_dict[setting_name]:\n                self._setting_changed_dict[page][setting_name] = value\n            elif (\n                value == old_dict[setting_name]\n                and setting_name in self._setting_changed_dict[page]\n            ):\n                self._setting_changed_dict[page].pop(setting_name)\n\n    def check_differences(self, new_dict, old_dict):\n        \"\"\"Changes settings in settings manager with changes from dialog.\n\n        Parameters\n        ----------\n        new_dict : dict\n            Dict that has the most recent changes by user. Each key is a setting parameter\n            and each item is the value.\n        old_dict : dict\n            Dict wtih values set at the beginning of the preferences dialog session.\n        \"\"\"\n        page = self._list.currentItem().text().split(\" \")[0].lower()\n        self._values_changed(page, new_dict, old_dict)\n        different_values = self._setting_changed_dict[page]\n\n        if len(different_values) > 0:\n            # change the values in SETTINGS\n            for setting_name, value in different_values.items():\n                try:\n                    setattr(SETTINGS._settings[page], setting_name, value)\n                    self._values_dict[page] = new_dict\n                except:  # noqa: E722\n                    continue\n\n\nclass ConfirmDialog(QDialog):\n    \"\"\"Dialog to confirms a user's choice to restore default settings.\"\"\"\n\n    valueChanged = Signal(bool)\n\n    def __init__(\n        self,\n        parent: QWidget = None,\n        text: str = \"\",\n    ):\n        super().__init__(parent)\n\n        # Set up components\n        self._question = QLabel(self)\n        self._button_restore = QPushButton(trans._(\"Restore\"))\n        self._button_cancel = QPushButton(trans._(\"Cancel\"))\n\n        # Widget set up\n        self._question.setText(text)\n\n        # Layout\n        button_layout = QHBoxLayout()\n        button_layout.addWidget(self._button_cancel)\n        button_layout.addWidget(self._button_restore)\n\n        main_layout = QVBoxLayout()\n        main_layout.addWidget(self._question)\n        main_layout.addLayout(button_layout)\n\n        self.setLayout(main_layout)\n\n        # Signals\n        self._button_cancel.clicked.connect(self.on_click_cancel)\n        self._button_restore.clicked.connect(self.on_click_restore)\n\n    def on_click_cancel(self):\n        \"\"\"Do not restore defaults and close window.\"\"\"\n        self.close()\n\n    def on_click_restore(self):\n        \"\"\"Restore defaults and close window.\"\"\"\n        SETTINGS.reset()\n        self.valueChanged.emit(True)\n        self.close()\n", "path": "napari/_qt/dialogs/preferences_dialog.py"}], "after_files": [{"content": "import json\n\nfrom qtpy.QtCore import QSize, Signal\nfrom qtpy.QtWidgets import (\n    QDialog,\n    QHBoxLayout,\n    QLabel,\n    QListWidget,\n    QPushButton,\n    QStackedWidget,\n    QVBoxLayout,\n    QWidget,\n)\n\nfrom ..._vendor.qt_json_builder.qt_jsonschema_form import WidgetBuilder\nfrom ...utils.settings import SETTINGS\nfrom ...utils.translations import trans\n\n\nclass PreferencesDialog(QDialog):\n    \"\"\"Preferences Dialog for Napari user settings.\"\"\"\n\n    ui_schema = {\n        \"call_order\": {\"ui:widget\": \"plugins\"},\n    }\n\n    resized = Signal(QSize)\n    closed = Signal()\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n\n        self._list = QListWidget(self)\n        self._stack = QStackedWidget(self)\n\n        self._list.setObjectName(\"Preferences\")\n\n        # Set up buttons\n        self._button_cancel = QPushButton(trans._(\"Cancel\"))\n        self._button_ok = QPushButton(trans._(\"OK\"))\n        self._default_restore = QPushButton(trans._(\"Restore defaults\"))\n\n        # Setup\n        self.setWindowTitle(trans._(\"Preferences\"))\n\n        # Layout\n        left_layout = QVBoxLayout()\n        left_layout.addWidget(self._list)\n        left_layout.addStretch()\n        left_layout.addWidget(self._default_restore)\n        left_layout.addWidget(self._button_cancel)\n        left_layout.addWidget(self._button_ok)\n\n        main_layout = QHBoxLayout()\n        main_layout.addLayout(left_layout, 1)\n        main_layout.addWidget(self._stack, 3)\n\n        self.setLayout(main_layout)\n\n        # Signals\n\n        self._list.currentRowChanged.connect(\n            lambda index: self._stack.setCurrentIndex(index)\n        )\n        self._button_cancel.clicked.connect(self.on_click_cancel)\n        self._button_ok.clicked.connect(self.on_click_ok)\n        self._default_restore.clicked.connect(self.restore_defaults)\n\n        # Make widget\n\n        self.make_dialog()\n        self._list.setCurrentRow(0)\n\n    def closeEvent(self, event):\n        \"\"\"Override to emit signal.\"\"\"\n        self.closed.emit()\n        super().closeEvent(event)\n\n    def reject(self):\n        \"\"\"Override to handle Escape.\"\"\"\n        super().reject()\n        self.close()\n\n    def resizeEvent(self, event):\n        \"\"\"Override to emit signal.\"\"\"\n        self.resized.emit(event.size())\n        super().resizeEvent(event)\n\n    def make_dialog(self):\n        \"\"\"Removes settings not to be exposed to user and creates dialog pages.\"\"\"\n\n        # Because there are multiple pages, need to keep a dictionary of values dicts.\n        # One set of keywords are for each page, then in each entry for a page, there are dicts\n        # of setting and its value.\n\n        self._values_orig_dict = {}\n        self._values_dict = {}\n        self._setting_changed_dict = {}\n\n        for page, setting in SETTINGS.schemas().items():\n            schema, values, properties = self.get_page_dict(setting)\n\n            self._setting_changed_dict[page] = {}\n            self._values_orig_dict[page] = values\n            self._values_dict[page] = values\n\n            # Only add pages if there are any properties to add.\n            if properties:\n                self.add_page(schema, values)\n\n    def get_page_dict(self, setting):\n        \"\"\"Provides the schema, set of values for each setting, and the properties\n        for each setting.\n\n        Parameters\n        ----------\n        setting : dict\n            Dictionary of settings for a page within the settings manager.\n\n        Returns\n        -------\n        schema : dict\n            Json schema of the setting page.\n        values : dict\n            Dictionary of values currently set for each parameter in the settings.\n        properties : dict\n            Dictionary of properties within the json schema.\n\n        \"\"\"\n\n        schema = json.loads(setting['json_schema'])\n        # Need to remove certain properties that will not be displayed on the GUI\n        properties = schema.pop('properties')\n        model = setting['model']\n        values = model.dict()\n        napari_config = getattr(model, \"NapariConfig\", None)\n        if napari_config is not None:\n            for val in napari_config.preferences_exclude:\n                properties.pop(val)\n                values.pop(val)\n\n        schema['properties'] = properties\n\n        return schema, values, properties\n\n    def restore_defaults(self):\n        \"\"\"Launches dialog to confirm restore settings choice.\"\"\"\n\n        widget = ConfirmDialog(\n            parent=self,\n            text=trans._(\"Are you sure you want to restore default settings?\"),\n        )\n        widget.valueChanged.connect(self._reset_widgets)\n        widget.exec_()\n\n    def _reset_widgets(self):\n        \"\"\"Deletes the widgets and rebuilds with defaults.\"\"\"\n        self.close()\n        self._list.clear()\n\n        for n in range(self._stack.count()):\n            widget = self._stack.removeWidget(self._stack.currentWidget())\n            del widget\n\n        self.make_dialog()\n        self._list.setCurrentRow(0)\n        self.show()\n\n    def on_click_ok(self):\n        \"\"\"Keeps the selected preferences saved to SETTINGS.\"\"\"\n        self.close()\n\n    def on_click_cancel(self):\n        \"\"\"Restores the settings in place when dialog was launched.\"\"\"\n        # Need to check differences for each page.\n        for n in range(self._stack.count()):\n            # Must set the current row so that the proper list is updated\n            # in check differences.\n            self._list.setCurrentRow(n)\n            page = self._list.currentItem().text().split(\" \")[0].lower()\n            # get new values for settings.  If they were changed from values at beginning\n            # of preference dialog session, change them back.\n            # Using the settings value seems to be the best way to get the checkboxes right\n            # on the plugin call order widget.\n            setting = SETTINGS.schemas()[page]\n            schema, new_values, properties = self.get_page_dict(setting)\n            self.check_differences(self._values_orig_dict[page], new_values)\n\n        self._list.setCurrentRow(0)\n        self.close()\n\n    def add_page(self, schema, values):\n        \"\"\"Creates a new page for each section in dialog.\n\n        Parameters\n        ----------\n        schema : dict\n            Json schema including all information to build each page in the\n            preferences dialog.\n        values : dict\n            Dictionary of current values set in preferences.\n        \"\"\"\n        widget = self.build_page_dialog(schema, values)\n        self._list.addItem(schema[\"title\"])\n        self._stack.addWidget(widget)\n\n    def build_page_dialog(self, schema, values):\n        \"\"\"Builds the preferences widget using the json schema builder.\n\n        Parameters\n        ----------\n        schema : dict\n            Json schema including all information to build each page in the\n            preferences dialog.\n        values : dict\n            Dictionary of current values set in preferences.\n        \"\"\"\n\n        builder = WidgetBuilder()\n        form = builder.create_form(schema, self.ui_schema)\n        # set state values for widget\n        form.widget.state = values\n        form.widget.on_changed.connect(\n            lambda d: self.check_differences(\n                d,\n                self._values_dict[schema[\"title\"].lower()],\n            )\n        )\n\n        return form\n\n    def _values_changed(self, page, new_dict, old_dict):\n        \"\"\"Loops through each setting in a page to determine if it changed.\n\n        Parameters\n        ----------\n        new_dict : dict\n            Dict that has the most recent changes by user. Each key is a setting value\n            and each item is the value.\n        old_dict : dict\n            Dict wtih values set at the begining of preferences dialog session.\n\n        \"\"\"\n        for setting_name, value in new_dict.items():\n            if value != old_dict[setting_name]:\n                self._setting_changed_dict[page][setting_name] = value\n            elif (\n                value == old_dict[setting_name]\n                and setting_name in self._setting_changed_dict[page]\n            ):\n                self._setting_changed_dict[page].pop(setting_name)\n\n    def check_differences(self, new_dict, old_dict):\n        \"\"\"Changes settings in settings manager with changes from dialog.\n\n        Parameters\n        ----------\n        new_dict : dict\n            Dict that has the most recent changes by user. Each key is a setting parameter\n            and each item is the value.\n        old_dict : dict\n            Dict wtih values set at the beginning of the preferences dialog session.\n        \"\"\"\n        page = self._list.currentItem().text().split(\" \")[0].lower()\n        self._values_changed(page, new_dict, old_dict)\n        different_values = self._setting_changed_dict[page]\n\n        if len(different_values) > 0:\n            # change the values in SETTINGS\n            for setting_name, value in different_values.items():\n                try:\n                    setattr(SETTINGS._settings[page], setting_name, value)\n                    self._values_dict[page] = new_dict\n                except:  # noqa: E722\n                    continue\n\n\nclass ConfirmDialog(QDialog):\n    \"\"\"Dialog to confirms a user's choice to restore default settings.\"\"\"\n\n    valueChanged = Signal(bool)\n\n    def __init__(\n        self,\n        parent: QWidget = None,\n        text: str = \"\",\n    ):\n        super().__init__(parent)\n\n        # Set up components\n        self._question = QLabel(self)\n        self._button_restore = QPushButton(trans._(\"Restore\"))\n        self._button_cancel = QPushButton(trans._(\"Cancel\"))\n\n        # Widget set up\n        self._question.setText(text)\n\n        # Layout\n        button_layout = QHBoxLayout()\n        button_layout.addWidget(self._button_cancel)\n        button_layout.addWidget(self._button_restore)\n\n        main_layout = QVBoxLayout()\n        main_layout.addWidget(self._question)\n        main_layout.addLayout(button_layout)\n\n        self.setLayout(main_layout)\n\n        # Signals\n        self._button_cancel.clicked.connect(self.on_click_cancel)\n        self._button_restore.clicked.connect(self.on_click_restore)\n\n    def on_click_cancel(self):\n        \"\"\"Do not restore defaults and close window.\"\"\"\n        self.close()\n\n    def on_click_restore(self):\n        \"\"\"Restore defaults and close window.\"\"\"\n        SETTINGS.reset()\n        self.valueChanged.emit(True)\n        self.close()\n", "path": "napari/_qt/dialogs/preferences_dialog.py"}]}