Skip to content

Commit 4fcdc10

Browse files
authored
Merge pull request #3567 from markotoplak/before_packing
Added settingsAboutToBePacked signal to OWWidget
2 parents cacc41a + 834cf7a commit 4fcdc10

File tree

5 files changed

+49
-21
lines changed

5 files changed

+49
-21
lines changed

Orange/widgets/data/owpythonscript.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from Orange.base import Learner, Model
2222
from Orange.widgets import widget, gui
2323
from Orange.widgets.utils import itemmodels
24-
from Orange.widgets.settings import Setting, SettingsHandler
24+
from Orange.widgets.settings import Setting
2525
from Orange.widgets.utils.widgetpreview import WidgetPreview
2626
from Orange.widgets.widget import OWWidget, Input, Output
2727

@@ -364,14 +364,6 @@ def select_row(view, row):
364364
QItemSelectionModel.ClearAndSelect)
365365

366366

367-
class PrepareSavingSettingsHandler(SettingsHandler):
368-
"""Calls storeSpecificSettings, which is currently not called from non-context handlers."""
369-
370-
def pack_data(self, widget):
371-
widget.storeSpecificSettings()
372-
return super().pack_data(widget)
373-
374-
375367
class OWPythonScript(widget.OWWidget):
376368
name = "Python Script"
377369
description = "Write a Python script and run it on input data or models."
@@ -397,8 +389,6 @@ class Outputs:
397389

398390
signal_names = ("data", "learner", "classifier", "object")
399391

400-
settingsHandler = PrepareSavingSettingsHandler()
401-
402392
libraryListSource = \
403393
Setting([Script("Hello world", "print('Hello world')\n")])
404394
currentScriptIndex = Setting(0)
@@ -528,6 +518,7 @@ def __init__(self):
528518
select_row(self.libraryView, self.currentScriptIndex)
529519

530520
self.restoreScriptText()
521+
self.settingsAboutToBePacked.connect(self.saveScriptText)
531522

532523
self.splitCanvas.setSizes([2, 1])
533524
if self.splitterState is not None:
@@ -537,9 +528,6 @@ def __init__(self):
537528
self.controlArea.layout().addStretch(1)
538529
self.resize(800, 600)
539530

540-
def storeSpecificSettings(self):
541-
self.saveScriptText()
542-
543531
def restoreScriptText(self):
544532
if self.scriptText is not None:
545533
current = self.text.toPlainText()

Orange/widgets/settings.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,12 @@ def _add_defaults(self, data):
489489
new_data.update(data)
490490
return new_data
491491

492+
def _prepare_defaults(self, widget):
493+
self.defaults = self.provider.pack(widget)
494+
for setting, data, _ in self.provider.traverse_settings(data=self.defaults):
495+
if setting.schema_only:
496+
data.pop(setting.name, None)
497+
492498
def pack_data(self, widget):
493499
"""
494500
Pack the settings for the given widget. This method is used when
@@ -504,6 +510,7 @@ def pack_data(self, widget):
504510
----------
505511
widget : OWWidget
506512
"""
513+
widget.settingsAboutToBePacked.emit()
507514
packed_settings = self.provider.pack(widget)
508515
packed_settings[VERSION_KEY] = self.widget_class.settings_version
509516
return packed_settings
@@ -517,10 +524,8 @@ def update_defaults(self, widget):
517524
----------
518525
widget : OWWidget
519526
"""
520-
self.defaults = self.provider.pack(widget)
521-
for setting, data, _ in self.provider.traverse_settings(data=self.defaults):
522-
if setting.schema_only:
523-
data.pop(setting.name, None)
527+
widget.settingsAboutToBePacked.emit()
528+
self._prepare_defaults(widget)
524529
self.write_defaults()
525530

526531
def fast_save(self, widget, name, value):
@@ -675,6 +680,7 @@ def update_defaults(self, widget):
675680
Merge the widgets local contexts into the global contexts and persist
676681
the settings (including the contexts) to disk.
677682
"""
683+
widget.settingsAboutToBePacked.emit()
678684
self.settings_from_widget(widget)
679685
globs = self.global_contexts
680686
assert widget.context_settings is not globs
@@ -683,7 +689,10 @@ def update_defaults(self, widget):
683689
globs.sort(key=lambda c: -c.time)
684690
del globs[self.MAX_SAVED_CONTEXTS:]
685691

686-
super().update_defaults(widget)
692+
# Save non-context settings. Do not call super().update_defaults, so that
693+
# settingsAboutToBePacked is emitted once.
694+
self._prepare_defaults(widget)
695+
self.write_defaults()
687696

688697
def new_context(self, *args):
689698
"""Create a new context."""

Orange/widgets/tests/test_context_handler.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from io import BytesIO
44
from unittest import TestCase
55
from unittest.mock import Mock, patch, call
6+
from AnyQt.QtCore import pyqtSignal as Signal, QObject
67
from Orange.widgets.settings import (
78
ContextHandler, ContextSetting, Context, Setting, SettingsPrinter,
89
VERSION_KEY, IncompatibleContext
@@ -11,13 +12,14 @@
1112
__author__ = 'anze'
1213

1314

14-
class SimpleWidget:
15+
class SimpleWidget(QObject):
1516
settings_version = 1
1617

1718
setting = Setting(42)
1819
schema_only_setting = Setting(None, schema_only=True)
1920

2021
context_setting = ContextSetting(42)
22+
settingsAboutToBePacked = Signal()
2123

2224
migrate_settings = Mock()
2325
migrate_context = Mock()
@@ -213,6 +215,18 @@ def test_close_context(self):
213215
handler.close_context(widget)
214216
self.assertEqual(widget.schema_only_setting, 0xD06F00D)
215217

218+
def test_about_pack_settings_signal(self):
219+
handler = ContextHandler()
220+
handler.bind(SimpleWidget)
221+
widget = SimpleWidget()
222+
handler.initialize(widget)
223+
fn = Mock()
224+
widget.settingsAboutToBePacked.connect(fn)
225+
handler.pack_data(widget)
226+
self.assertEqual(1, fn.call_count)
227+
handler.update_defaults(widget)
228+
self.assertEqual(2, fn.call_count)
229+
216230

217231
class TestSettingsPrinter(TestCase):
218232
def test_formats_contexts(self):

Orange/widgets/tests/test_settings_handler.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from unittest.mock import patch, Mock
99
import warnings
1010

11+
from AnyQt.QtCore import pyqtSignal as Signal, QObject
12+
1113
from Orange.tests import named_file
1214
from Orange.widgets.settings import SettingsHandler, Setting, SettingProvider,\
1315
VERSION_KEY, rename_setting, Context, migrate_str_to_variable
@@ -342,13 +344,25 @@ def override_default_settings(self, widget, defaults=None):
342344
if os.path.isfile(filename):
343345
os.remove(filename)
344346

347+
def test_about_pack_settings_signal(self):
348+
handler = SettingsHandler()
349+
handler.bind(SimpleWidget)
350+
widget = SimpleWidget()
351+
handler.initialize(widget)
352+
fn = Mock()
353+
widget.settingsAboutToBePacked.connect(fn)
354+
handler.pack_data(widget)
355+
self.assertEqual(1, fn.call_count)
356+
handler.update_defaults(widget)
357+
self.assertEqual(2, fn.call_count)
358+
345359

346360
class Component:
347361
int_setting = Setting(42)
348362
schema_only_setting = Setting("only", schema_only=True)
349363

350364

351-
class SimpleWidget:
365+
class SimpleWidget(QObject):
352366
settings_version = 1
353367

354368
setting = Setting(42)
@@ -357,8 +371,10 @@ class SimpleWidget:
357371
non_setting = 5
358372

359373
component = SettingProvider(Component)
374+
settingsAboutToBePacked = Signal()
360375

361376
def __init__(self):
377+
super().__init__()
362378
self.component = Component()
363379

364380
migrate_settings = Mock()

Orange/widgets/widget.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class OWWidget(QDialog, OWComponent, Report, ProgressBarMixin,
177177
#: :type: list of :class:`Message`
178178
UserAdviceMessages = []
179179

180+
settingsAboutToBePacked = Signal()
180181
contextAboutToBeOpened = Signal(object)
181182
contextOpened = Signal()
182183
contextClosed = Signal()

0 commit comments

Comments
 (0)