Skip to content

Develop v1.0.0 - #2

Open
ThomasMalletCodra wants to merge 131 commits into
mainfrom
develop
Open

Develop v1.0.0#2
ThomasMalletCodra wants to merge 131 commits into
mainfrom
develop

Conversation

@ThomasMalletCodra

Copy link
Copy Markdown

No description provided.

ThomasMalletCodra and others added 30 commits January 14, 2026 16:16
…(complete h5 module extract from DataLab)

- complete h5 module extract from DataLab
- add config for tests, utils and sigimax lib
- extract env module from DataLab
…pendancies and add TODO for those to discuss(adapter_plotpy))
…datalb mainwindow import), minimal support on dock module
Prevent the module-level SigimaX execution environment from parsing command
line arguments during import.

- Add an explicit parse_args parameter to SGMXExecEnv.
- Disable automatic parsing for the global SigimaX execenv singleton.
- Parse arguments explicitly from sigimax.app.run().
- Let derived applications keep ownership of their command-line arguments.

This prevents SigimaX from intercepting DataLab-specific options such as
--version before the derived DataLab environment is initialized.

Validated with Ruff and the SigimaX test suite: 155 tests passed.
Replace private main-window orchestration methods with protected extension
hooks while preserving the existing SigimaX setup and shutdown order.

Add pre/post setup hooks and expose status bar, actions, central widget,
menus, console, geometry, state, toolbar, dock, memory, and color-mode
lifecycle steps for derived applications.

Also align the HDF5 browser extension signature and add a derived-window
test that verifies hook overridability and call order.

Validated with Ruff, Pylint (10/10), and 156 SigimaX tests.
Extend the protected main-window lifecycle surface for derived applications.

- Add setup, console, dock, memory, modified-state, post-show, and shutdown hooks.
- Share generic console creation and visibility handling.
- Share standard HDF5, quit, and toolbar action creation.
- Make stable-release checks use the active derived-application version.
- Expose close cleanup stages while preserving shutdown order.
- Add lifecycle hook tests covering setup and close ordering.

Validated with Ruff, Pylint (10/10), and 156 SigimaX tests.
Make the application window factory preserve the concrete derived window
type through a bounded generic type, avoiding casts in downstream apps.

Improve splash resource loading for derived applications:

- load explicit paths directly
- resolve basenames through guidata image paths
- fall back safely when the configured resource is missing
- preserve optional progress-message behavior

Add tests for registered-resource resolution, missing-image fallback, and
disabled progress messages.

Validated with Ruff, Pylint (10/10), and 159 SigimaX tests.
* [UPDATE] : sigimax/config.py:
        - remove unused environment-variable synchronization from application options
        - simplify get, set, context, serialization, and reset operations
        - add an option_changed hook for derived application persistence
    * [UPDATE] : sigimax/tests/config/test_config_fields.py:
        - adapt option field tests to the simplified API
        - cover option change notifications and context restoration
        - remove environment synchronization tests
    * [UPDATE] : sigimax/tests/config/test_options_subclass.py:
        - update derived option tests to use the simplified API
    * [UPDATE] : sigimax/tests/mainwindow/test_derived_app.py:
        - remove environment-specific configuration setup
    * [UPDATE] : README.md:
        - document in-memory options and JSON persistence without cross-process claims
    * [UPDATE] : doc/index.rst:
        - update the derived application configuration example
    * [UPDATE] : doc/examples/features/configuration.py:
        - simplify configuration field usage
    * [UPDATE] : doc/examples/getting_started/minimal_app.py:
        - remove obsolete environment option declarations
    * [UPDATE] : doc/examples/use_cases/full_app.py:
        - use the simplified application option API
    * [UPDATE] : doc/user_guide/features.rst:
        - remove unsupported environment synchronization documentation
    * [UPDATE] : doc/user_guide/getting_started.rst:
        - update the configuration derivation workflow
    * [UPDATE] : doc/user_guide/overview.rst:
        - align the configuration feature summary
    * [UPDATE] : doc/release_notes/release_0.01.md:
        - describe JSON persistence without environment overrides
Require derived applications to implement workspace persistence instead
of acknowledging a base save without writing data.

Document the HDF5 ownership boundary and the tested reference
application while preserving DataLab native workspace behavior.
Create singleton instances from the requested derived window class and
run protected setup before virtual startup hooks.

Document the lifecycle contract and demonstrate it in the HDF5 reference
application.
Read plotpy.config.MAIN_FG_COLOR/MAIN_BG_COLOR at call time instead of
capturing them at import time, so re-applying defaults after a color mode
change uses the current theme colors.

Split initialize_plotpy() into apply_plotpy_defaults() and
set_plotpy_application(), and re-apply the defaults from
SGMXMainWindow._update_color_mode.

Assisted-by: Claude Opus 5
Fields whose get/set transform the stored value could not survive a
get/set round-trip, making to_dict/from_dict and reset_to_defaults
incorrect for them. Add to_storage/from_storage (identity by default)
and route container serialization through them. Fields also declare
storage_suffixes and storage_escape so storage backends can handle
multi-key and escaped values without type introspection.
Add two declaration-time attributes to OptionField: `storage_key`, which
overrides the storage key derived from the option name, and `runtime`, which
marks a value shared between processes through the storage backend and
therefore excluded from bulk saves.

Declare `storage_key="max_line_count"` on `console_max_line_count`, so that
its historical INI key no longer needs an override table in the consuming
application.

Assisted-by: Claude Opus 5
Move ConfigPathOptionField, WorkingDirOptionField, FormatStringOptionField
and DataSetOptionField from DataLab into sigimax.config, and merge the
DataLab FontOptionField subclass into the SigimaX one (font family
resolution and get_font).

Use the new field types for the options that need them:
- traceback_log_path/faulthandler_log_path become ConfigPathOptionField
  and now resolve to absolute paths inside the configuration directory;
- base_dir becomes WorkingDirOptionField and accepts a file path, storing
  its parent directory.

Also derive the app_name default from APP_NAME instead of hardcoding it,
so derived applications get their own name without extra wiring.

Assisted-by: Claude Opus 5
The Section/Option class hierarchy (Option, FontOption, ConfigPathOption,
WorkingDirOption, EnumOption, DataSetOption) and its two metaclasses were
superseded by the typed option fields in sigimax.config and no longer had
any consumer, in SigimaX or in derived applications.

sigimax.utils.conf now only holds the INI backend actually in use:
AppUserConfig, the CONF singleton and the Configuration helper.

Assisted-by: Claude Opus 5
…sable

Audit of every `import-outside-toplevel` / `cyclic-import` disable in application code
- sigimax/utils/qthelpers.py: remove an orphan `disable=import-outside-toplevel`
  left behind by a removed local import

Assisted-by: Claude Opus 5
…code

Remove code that was copied verbatim from SGMXMainWindow during the
SigimaX migration and is now inherited unchanged:

* __update_tab_icon_size: renamed to _update_tab_icon_size in SigimaX so
  subclasses can reuse it instead of redefining it

Assisted-by: Claude Opus 5
…on point

_add_dockwidget() now owns the whole dock lifecycle: it registers the dock
in self.docks, assigns a stable Qt object name and performs tabification,
through the new name, key and tabify_with keyword arguments.

Derived applications no longer have to call create_dockwidget(),
addDockWidget() and update self.docks by hand, which was error-prone and
left docks unregistered.

self.docks is retyped as dict[QWidget, QDockWidget]: it was annotated with
DockableConsole although any dockable widget could be used as a key.

Dock object names are no longer the translated dock titles, so that the
saved layout survives a language change. Window states are therefore saved
and restored with WINDOW_STATE_VERSION, which makes Qt discard layouts
persisted by an earlier version instead of restoring them partially.

The example and test applications are updated to use the new API.

Assisted-by: Claude Opus 5
setup() used to be a short, monolithic sequence, so derived applications
had to override it entirely and duplicate the base steps. It now calls
three optional hooks, all no-ops by default:

* _setup_panels(), after the global actions, so that panel toolbars are
  added after the main toolbar and before the central widget is built
* _setup_docks(), for application dock widgets
* _post_setup(), to finalize the user interface once panels, central
  widget, menus, console and docks all exist

_restore_state() stays the last step, which the docstring now states
explicitly: docks added afterwards keep their default geometry instead of
the persisted one.

The example and test applications previously added their docks right
after super().__init__(), i.e. after the window state had been restored,
and therefore never got their persisted layout back. They now use
_setup_docks() and _post_setup(), and document the intended pattern.

Assisted-by: Claude Opus 5
…elp menu

The menu bar was hardcoded in _add_menus(), so a derived application adding
its own menus had to reimplement the whole method, including the creation
and wiring of the standard File, View and Help menus.

_get_menubar_layout() now returns the menu bar as an ordered list of
(attribute name, title) pairs, which _add_menus() turns into menus stored as
self.<name>_menu. Subclasses insert their own menus by overriding that single
method.

The help menu actions are likewise split into three overridable groups,
_get_help_doc_actions(), _get_help_support_actions() and
_get_help_about_actions(), so that an application can append its own entries
to the relevant group instead of rebuilding the whole list.

Assisted-by: Claude Opus 5
…e plot dock

The curve statistics label functions were a hand-written list, including
NaN-robust helpers (nan_min_max, nan_delta, nan_mean, nan_std) written before
PlotPy provided its own. CurveStatsTool.LABELFUNCS is now NaN-robust, so the
list is built from it and only the pulse-related entries (FWHM, rise and fall
times) are appended. The YRangeCursorTool entries likewise come from PlotPy
instead of being hardcoded, which also fixes the sum of y being computed as a
trapezoidal integral instead of a plain sum.

Two extension points are added so that an application can specialize the plot
dock without reimplementing it:

* SigimaXPlotWidget._customize_image_panels(), called once the image tools are
  registered, to customize the X and Y cross section panels
* DockablePlotWidget.PLOTWIDGET_CLASS, which selects the plot widget class the
  dock instantiates

SGMXMainWindow._update_extra_color_mode() is added as well, so that derived
applications refresh their own widgets while window updates are disabled,
instead of overriding the whole colour mode update.

Assisted-by: Claude Opus 5
open_h5_files() resolved reset_all, asking the user a modal question, then
handed it over to browse_h5_files() and import_h5_file(), which both discarded
it. A derived application could therefore be asked whether the workspace
should be cleared, and see the answer ignored.

The HDF5 surface is restructured as one orchestrator, three import primitives
and a single convergence point:

* _handle_imported_objects() now receives the imported objects and reset_all.
  It clears the workspace when requested, then emits SIG_SEND_OBJECTLIST.
  Derived applications override it to feed their own data model instead of
  duplicating a whole import method.
* import_h5_file() is renamed import_all_from_h5_file(). The former name was
  also used by derived applications for a browser-based import, i.e. with the
  opposite meaning, while the base implementation imports every supported
  dataset without any dialog.

Two hooks let a derived application drive the "clear workspace" question
without reimplementing the orchestrator:

* _is_workspace_empty(), so the question is skipped when no identifier
  conflict is possible. The base window has no data model and returns False.
* _get_clear_workspace_message(), for application-specific wording.

Assisted-by: Claude Opus 5
_configure_statusbar() built a fixed status bar, so a derived application had
to reimplement the whole method - including the welcome message, the console
status and the memory status - just to insert its own indicators.

_get_extra_status_widgets() now returns the application-specific widgets, and
the base adds them between the console status and the memory status. The base
therefore owns the ordering, and a derived application only declares what to
add.

The defensive "self.docks is not None" check in _update_color_mode is dropped:
the registry is always a dictionary.

Assisted-by: Claude Opus 5
…d applications

The adapter factories hard-coded the concrete adapter classes, so a derived
application could not substitute an adapter or register an additional object
type without forking the whole dispatch chain.

Introduce PlotPyAdapterFactory, exposing the object and plot-item dispatch as
two overridable methods, together with get/set/reset_adapter_factory following
the existing get_conf/set_conf/reset_conf pattern. Route converters and the ROI
factory through the active factory so that SigimaX components honour a derived
application's adapters, whatever the import order. Public entry points keep
their signature, so no call site changes.

Also promote DataLab's signal ROI adapters, which depended on nothing outside
sigima and sigimax: ROI fills are now clipped to the signal curve instead of
covering the whole canvas height, and sibling ROIs cycle through a color
palette indexed by ROI title, so the color stays stable across deletions.

Assisted-by: Claude Opus 5
- test_fitdialog.py: port DataLab's interactive fit metadata regression
  suite (canonical fit_params, signed amplitude bounds, evaluable
  round-trip) onto sigimax.widgets.fitdialog
- test_warningerror.py: add WarningErrorMessageBox construction test
  (dialog was undocumented/untested)
- test_config_fields.py: add ConfigPathOptionField, WorkingDirOptionField,
  DataSetOptionField and FontOptionField.get_font coverage
- test_h5_utils.py: add is_single_str_array, is_supported_str_dtype and
  process_scalar_value/process_label/process_xy_values coverage
- test_h5_common_collect_attributes.py (new): regression test for the
  DIMENSION_LIST/REFERENCE picklability fix in h5/common.py
- test_coordutils.py (new): port adapters_plotpy.coordutils rounding tests

Complements 2104a59 (source-side port of the same DataLab develop fixes).

Assisted-by: Claude Opus 5
Assisted-by: Claude Sonnet/Opus 5
Assisted-by: Claude Sonnet 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants