Uh oh!
There was an error while loading. Please reload this page.
Conversation
RoboticWidget: running indicator, Start/Stop, current-task panel (name, target, obsnum, started, ETA/countdown), next-up + cant_run_reason. ScheduleWidget: schedule table (start/end/task/target/state/priority), "Re-schedule now" (proxy -> run()), Start/Stop. Both registered in DEFAULT_WIDGETS/DEFAULT_ICONS/DEFAULT_CONFIG. Requires pyobs-core with IRobotic/IRoboticScheduler, which is on develop but unreleased -- see specs/2026-08-31-irobotic-widgets.md. test/robotic.yaml added for manual/visual testing against DummyMastermind + DummyScheduler.
…lity Column widths now fit their content (start/end/task/target/state/ priority vary a lot) instead of the designer's equal-width default. test/robotic.yaml: raised blocked_probability to 0.6 so the "next up" panel is visible more often during manual testing -- it's only populated during a simulated "can't run" wait, by design (matches the real Mastermind), so it's often empty at the 0.2 default.
labelAutonomousWarning had no maximumHeight and was rendering huge in practice (pre-existing pyobs-gui issue, unrelated to #825, surfaced while visually testing this branch's test/robotic.yaml since DummyMastermind auto-starts running). Capped to 32px. ScheduleWidget: switched from per-column ResizeToContents to Stretch (equal-width columns filling the full table width) -- looked bad with content-fitted widths.
pyobs-core 2.1.0 is now released, resolving this PR's earlier blocker. CI was failing pyrefly because uv.lock still pinned 2.0.0. Verified locally against a real (non-editable) sync of the published package: pytest, ruff, and pyrefly all clean.
Add RoboticWidget/ScheduleWidget for IRobotic/IRoboticScheduler (#825)
…add VideoWidget split follow-up Revise 2026-08-28-gui-main-vs-sidebar-widgets.md: a sidebar_preferred promotion rule replaces the naive "keep every match" collection (fixes camera+filters showing filter controls twice), and the sidebar container becomes universal instead of >=2-widgets-only (fixes custom sidebar: entries being silently invisible on modules like a bare roof). Adds the paired_sidebar_widget mechanism (D6); its first consumer (splitting VideoWidget into a live-view main widget + controls sidebar widget) is tracked in a new follow-up plan.
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.16.2 to 0.16.5. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](astral-sh/ruff@0.16.2...0.16.5) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.16.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
chore(deps-dev): bump ruff from 0.16.2 to 0.16.5
Replaces the interface -> widget dict (first-match-wins, silently dropping every other interface a module implements) with an ordered MAIN_WIDGETS registry plus collect_main_widgets(): a module matching several main widgets now gets one nav entry whose page is a tab widget, one tab per widget, with a shared sidebar (ModulePage) that's the universal page host regardless of match count. Sidebar-preferred interfaces (filters, focuser, temperatures, cooling) demote into the sidebar when another main widget already matched, and promote back to their own page/tabs when nothing else did. Partial widget-open failures drop just that tab instead of tearing down the whole page. Custom widgets:/sidebar: config gained real interface-targeted replace and overwrite semantics. The VideoWidget split (D6's first paired_sidebar_widget consumer) is tracked separately.
Fake interface/widget registry so the promotion rule, universal ModulePage, custom widgets:/sidebar: config, disconnect teardown, FITS-header aggregation and D5 partial-open-failure handling are all exercised without needing real comm plumbing. Updates the two existing DEFAULT_WIDGETS/DEFAULT_ICONS assertions for the new registry shape.
…ract Also records that the DEFAULT_CONFIG deletion (D1) has no maintainer objection -- deleting outright, no fallback constant.
ALWAYS_SIDEBAR_WIDGETS unconditionally added FITS-header controls to every module's sidebar (roof, weather, standalone filter wheel, ...), but that panel only makes sense for modules that actually write FITS files. Move it to a per-entry sidebar=((None, FitsHeadersWidget), ...) declaration on the ICamera and IVideo MAIN_WIDGETS rows instead (and CameraWidget.sidebar_fills, restoring its pre-registry behavior), and leave ALWAYS_SIDEBAR_WIDGETS empty -- kept as a mechanism for genuinely interface-agnostic sidebar content, per D2, just unused for now.
1. HIGH, confirmed: Camera's/Telescope's declared sidebar tuples fully overlapped their own sidebar_preferred registry entries (IFilters, ICooling, ITemperatures, IFocuser), so every one of those widgets was added to the sidebar twice. Drop the redundant declarations (registry and sidebar_fills class attributes) and add an interface-keyed dedup in open_module_page() as a second line of defense, so a future entry can't silently reintroduce the same duplication. WidgetChoice now carries the MAIN_WIDGETS interface it originated from (or the slot it's replacing, for a custom widgets: entry) so the dedup still holds when a demoted slot has been custom-replaced. 2. MEDIUM, spec deviation: implement D5's promised sidebar-widget failure isolation in BaseWidget.add_to_sidebar() -- a failing sidebar widget is now logged and dropped instead of propagating and tearing down the whole page. Also drops the redundant explicit .open() call on demoted sidebar_preferred widgets (add_to_sidebar already opens them via _open_child), which is what makes their failures go through the same isolation as every other sidebar fill. 3. LOW: interface: custom config can now target an interface that's currently demoted into the sidebar (sidebar_preferred), not just a plain main-widget slot -- collect_main_widgets() falls back to looking it up there before logging "module doesn't implement it". 4. LOW: interface: combined with overwrite: true now logs a warning that interface-replace wins and overwrite is ignored, instead of silently doing so. 5. LOW: ModuleWindow.open() now raises when open_module_page() reports every main widget failed, matching how the old single-widget code surfaced a total failure, instead of leaving a silent empty page. Nit: base.py's register_event() docstring still referenced the deleted DEFAULT_WIDGETS. Adds 5 regression tests (79 total, up from 74).
horizontalLayout had no explicit margins, so its QGroupBox border sat inset by Qt's default layout margin instead of flush with the sidebar column like the other two sidebar-preferred widgets.
The shared sidebar (D2) aggregates fills across every tab, so it can grow taller than any single old widget's hand-picked sidebar did. Wrap widgetSidebar in a QScrollArea: vertical-as-needed, horizontal always off, frameless to keep the same visual look when it fits.
Main widgets vs. sidebar widgets, automatic tab pages for multi-widget modules (#150)
Adds StructuredConfigWidget: a nested form auto-built from a module's ConfigSchema (str/int/float/bool/enum plus recursive objects), populated from ConfigAppliedState and applied via set_config(). No widget code needed per module. Registered in MAIN_WIDGETS as a fallback/companion page for any IStructuredConfig module.
…dget verification Used to smoke-test the widget against DummyStructuredConfig (pyobs-core#841) in a local MultiModule + LocalComm setup, same pattern as the other test/*.yaml fixtures.
Generic IStructuredConfig widget, schema-driven config form (#154)
Current pyobs-core develop's stricter leftover-kwarg check in Object.__init__ has no `name` parameter anywhere in the Module/Object chain, so every fixture's redundant module-level `name: <module>` (the dict key already names it; only comm: needs its own `name:`) now raises TypeError on construction. Verified against the unmodified files before this fix (e.g. roof.yaml failed the same way). full.yaml/video.yaml still fail separately on a stale `port` kwarg to DummyVideo -- same root cause, different field, left for a follow-up.
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
version 2.1.0