-
Notifications
You must be signed in to change notification settings - Fork 161
Add preferences dialog #2899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add preferences dialog #2899
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2899 +/- ##
==========================================
+ Coverage 56.45% 56.56% +0.10%
==========================================
Files 535 536 +1
Lines 62264 62420 +156
Branches 7711 7729 +18
==========================================
+ Hits 35154 35309 +155
- Misses 25345 25348 +3
+ Partials 1765 1763 -2 ☔ View full report in Codecov by Sentry. |
563948b
to
548c6b9
Compare
548c6b9
to
d92f96a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: This was meant to be "Request changes" because preferencesDialog.py
has a bug in an else-raise-clause due to variable naming, default_config
should be deleted (I think) and the flat_dict
should be explained or removed.
Really nice, the widget generator and the prefs based on pydantic will make it pretty easy to extend the configurable options in the future.
I see a potential for confusion because we have a preferences.json
, which the user can locate with Open Config Folder
- but these are the volumina preferences. Now we have a Preferences dialog that controls a different set of preferences that we internally call config.
From the dev perspective, it might be worth just adding a short note to the respective docstrings to explain that ilastik-config goes with PreferencesDialog and that these are separate from preferences
, which is from volumina. Though the code is easy enough to trace anyway.
From the user perspective, I'm not really sure what can be done. Maybe creating the ilastik.ini file with the default values could help, so that at least if a user uses Open Config Folder, they can see that there are in fact two separate sets of settings?
* removed flattening of config dict - just works without * removed `default_config` (not used) -> moved information docstring as example * removed qtbot fixture from test that don't need it * renamed `Increment.increment` member to `inc` to avoid confusion Co-authored-by: Benedikt Best <[email protected]>
Co-authored-by: Benedikt Best <[email protected]>
Some options are not validated very well. For now we hide those to prevent changing them without much consideration.
3141217
to
39eaca2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:/
I realised there's an issue with coupling the dialog's model directly to the in-use runtime config: Regardless of whether you Ok or Cancel the dialog (which governs whether you write to disk), any non-default values you entered in the inputs are kept in the active runtime config. Also, if a non-default value was read from file, then resetting it to default in the dialog and clicking Ok doesn't actually transfer the value to the model.
The dialog does tell the user to please restart ilastik, but that should only be a precaution and not a requirement in order for Ok and Cancel to modify (or not modify) the ongoing runtime configs...
Request changes because there's also a remaining usage of the old config dict syntax in dataExportGui: settingsDlg = DataExportOptionsDlg(self, opExportModelOp, cfg["ilastik"]["output_filename_format"])
return widget, advanced | ||
|
||
def initUI(self): | ||
self._main_layout = QVBoxLayout() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I look at it again, I think all the layouts and widgets instantiated here can be local variables instead of self.
properties, as they're not referenced in any other method or outside the class 😅
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) | ||
self.resetButton = QPushButton("Reset to Defaults") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can see, buttonBox and resetButton aren't referenced outside the class, so prefix _
? (Or as suggested in the other comment, make them all local variables only?)
# adv_chbox_layout = QHBoxLayout() | ||
self._adv_checkbox = QCheckBox("Show advanced options") | ||
self._adv_checkbox.setTristate(False) | ||
self._adv_checkbox.stateChanged.connect(lambda x: self._update_advanced_view(x != 2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# adv_chbox_layout = QHBoxLayout() | |
self._adv_checkbox = QCheckBox("Show advanced options") | |
self._adv_checkbox.setTristate(False) | |
self._adv_checkbox.stateChanged.connect(lambda x: self._update_advanced_view(x != 2)) | |
self._adv_checkbox = QCheckBox("Show advanced options") | |
self._adv_checkbox.setTristate(False) | |
self._adv_checkbox.stateChanged.connect(lambda state: self._update_advanced_view(state != Qt.Checked)) |
pref_dict = self.config.model_dump(exclude_defaults=True) | ||
cf = configparser.ConfigParser() | ||
cf.read_dict(pref_dict) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pref_dict = self.config.model_dump(exclude_defaults=True) | |
cf = configparser.ConfigParser() | |
cf.read_dict(pref_dict) | |
unvalidated = self.config.model_dump(exclude_defaults=True) | |
self.config = self.config.model_validate(unvalidated) | |
validated = self.config.model_dump(exclude_defaults=True) | |
cf = configparser.ConfigParser() | |
cf.read_dict(validated) |
So that the stripped results are saved to file
This PR makes the settings, so far governed only by
ilastik.ini
, accessible to users via the UI:In the process I introduced a config class based on
pydantic
. The settings, edited via the dialog, will be written toilastik.ini
- this is fully compatible with the settings file so far. Note: Only settings different to default values are written to the file.Currently a full config would look like this:
Example
ilastik.ini
Todos:
pydantic
(pydantic-settings
, maybe) 🤡in the end
pydantic-settings
wasn't worth it - we don't want most of it's features (no need for .env files, we don't want to expose every setting via env variables, and also not via argparse (let alone that all of these would need to be customized to integrate with our current "interface")Checklist
Fixes #2863