ms-components 0.4.0__tar.gz → 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ms_components-0.4.0 → ms_components-0.4.2}/PKG-INFO +1 -1
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/widget.py +10 -1
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_tutorial/controller.py +5 -1
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_tutorial/overlay.py +45 -12
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/PKG-INFO +1 -1
- ms_components-0.4.2/src/ms_components.egg-info/scm_version.json +8 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_dock_window.py +20 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_tutorial.py +68 -0
- ms_components-0.4.0/src/ms_components.egg-info/scm_version.json +0 -8
- {ms_components-0.4.0 → ms_components-0.4.2}/.github/workflows/docs.yml +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/.github/workflows/publish.yml +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/.gitignore +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/LICENSE +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/MANIFEST.in +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/README.md +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/examples/tutorial_demo.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/examples/tutorial_demo.toml +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/licenses/qt-themes-LICENSE.txt +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/pyproject.toml +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/setup.cfg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/backdrop.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/base.qss +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/chips.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ketcher.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/listview.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/resources/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/resources/icons/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/resources/icons/folder.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_executors.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/bridge.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/cards.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/config.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/detail_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/formatting.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/job_cards.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/models.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/palette.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/polling.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_monitor/widget.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/app.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/backend.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/browser.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/scratch.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_projects/widget.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/actions.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/box.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/center.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/display.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/hide.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/hydrogens-polar.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/hydrogens.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/menu.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/orient.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/presets.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/rock.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/selection.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/settings.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/style.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/zoom.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/plugins.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/scene.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/widget.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_settings/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_settings/panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_stepper.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/action_header.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/cell_delegate.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/column_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/example_usage.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/filter_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/columns.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/export.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/filter.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/menu.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/reload.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/search.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/settings.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/sort-asc.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/sort-desc.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/icons/sort.svg +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/metric_filter_bar.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/pagination_control.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/query_builder.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/session_provider.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/smart_table_view.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/sort_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/table_config.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/table_interaction.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/table_model.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/test_external_filters.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/test_toolbar.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_tutorial/__init__.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_tutorial/bindings.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_tutorial/models.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/opengl.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/pagination.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/palettes.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/step_dialog.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/theme.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/tool_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/wheel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/SOURCES.txt +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/dependency_links.txt +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/requires.txt +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/scm_file_list.json +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components.egg-info/top_level.txt +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/conftest.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_app_settings.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_chips.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_executors_ui.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_ketcher.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_molsuite_monitor_bridge.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_molsuite_monitor_widgets.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_monitor_config.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_ms_projects_widget.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_opengl.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_progress_column.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_project_browser.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_pymol_grid.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_pymol_scene.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_pymol_toolbar.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_query_builder_keyset.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_shift_hscroll.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_split_button_style.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_step_dialog.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_table_interaction.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_table_toolbar.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_table_view_state.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_theme_contrast.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/tests/test_tool_panel.py +0 -0
- {ms_components-0.4.0 → ms_components-0.4.2}/zensical.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ms_components
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: PySide6 UI components for MolSuite: smart table, project browser, job monitor, PyMOL dock, steppers.
|
|
5
5
|
Author: Mario S. Valdés-Tresanco, Mario E. Valdés-Tresanco
|
|
6
6
|
License-Expression: MIT
|
|
@@ -779,6 +779,7 @@ class DockManager:
|
|
|
779
779
|
# Standalone action buttons (no dock): a click runs a callback instead of toggling a dock.
|
|
780
780
|
# action_id -> {"region", "order", "button"}. Re-added on every _build_toolbars().
|
|
781
781
|
self.action_buttons: Dict[str, dict] = {}
|
|
782
|
+
self.action_separators: Dict[str, dict] = {} # same shape; "button" is a ToolbarSeparator
|
|
782
783
|
self.region_states: Dict[Region, RegionState] = {
|
|
783
784
|
region: RegionState(order=[], visible=[]) for region in Region
|
|
784
785
|
}
|
|
@@ -885,6 +886,14 @@ class DockManager:
|
|
|
885
886
|
self._build_toolbars()
|
|
886
887
|
return button
|
|
887
888
|
|
|
889
|
+
def add_action_separator(self, separator_id: str, *, region: Region, order: int) -> None:
|
|
890
|
+
"""A line in a toolbar region, placed by ``order`` like an action button, so it survives
|
|
891
|
+
the rebuilds a line inserted into the layout would not."""
|
|
892
|
+
if separator_id in self.action_separators:
|
|
893
|
+
raise ValueError(f"Duplicate action separator id: {separator_id}")
|
|
894
|
+
self.action_separators[separator_id] = {"region": region, "order": int(order), "button": ToolbarSeparator()}
|
|
895
|
+
self._build_toolbars()
|
|
896
|
+
|
|
888
897
|
# ── Build ────────────────────────────────────────────────────
|
|
889
898
|
|
|
890
899
|
def build(self):
|
|
@@ -1595,7 +1604,7 @@ class DockManager:
|
|
|
1595
1604
|
# dock buttons keep their (possibly drag-set) region order; standalone action
|
|
1596
1605
|
# buttons are woven in by their `order` relative to the dock entries' orders.
|
|
1597
1606
|
merged = [(entry.order, self.buttons[entry.id]) for entry in self._region_entries(region)]
|
|
1598
|
-
for action in self.action_buttons.values():
|
|
1607
|
+
for action in (*self.action_buttons.values(), *self.action_separators.values()):
|
|
1599
1608
|
if action["region"] != region:
|
|
1600
1609
|
continue
|
|
1601
1610
|
idx = next((i for i, (order, _) in enumerate(merged) if order > action["order"]), len(merged))
|
|
@@ -56,12 +56,14 @@ class TutorialController(QObject):
|
|
|
56
56
|
events: Mapping[str, TutorialEvent] | None = None,
|
|
57
57
|
instruction_provider: Callable[[TutorialStep], str] | None = None,
|
|
58
58
|
dim_background: bool = True,
|
|
59
|
+
close_only: bool = False,
|
|
59
60
|
parent: QObject | None = None):
|
|
60
61
|
super().__init__(parent)
|
|
61
62
|
self.targets = dict(targets)
|
|
62
63
|
self.events = dict(events or {})
|
|
63
64
|
self.instruction_provider = instruction_provider
|
|
64
65
|
self.dim_background = dim_background
|
|
66
|
+
self.close_only = close_only
|
|
65
67
|
self._tutorial: Tutorial | None = None
|
|
66
68
|
self._index = -1
|
|
67
69
|
self._completed: set[str] = set()
|
|
@@ -93,6 +95,8 @@ class TutorialController(QObject):
|
|
|
93
95
|
def start(self, tutorial: Tutorial):
|
|
94
96
|
"""Validate bindings before replacing the active tour. Must run in the UI thread."""
|
|
95
97
|
for step in tutorial.steps:
|
|
98
|
+
if self.close_only and step.advance_on is None:
|
|
99
|
+
raise ValueError("Close-only tutorials require an event for every step")
|
|
96
100
|
if not isinstance(self.targets.get(step.target), TutorialTarget):
|
|
97
101
|
raise ValueError(f"Unregistered tutorial target: {step.target}")
|
|
98
102
|
if step.advance_on is not None and not isinstance(self.events.get(step.advance_on), TutorialEvent):
|
|
@@ -217,7 +221,7 @@ class TutorialController(QObject):
|
|
|
217
221
|
if self.overlay is not None:
|
|
218
222
|
self.overlay.hide()
|
|
219
223
|
self.overlay.deleteLater()
|
|
220
|
-
self._overlay = TutorialOverlay(host, dim_background=self.dim_background)
|
|
224
|
+
self._overlay = TutorialOverlay(host, dim_background=self.dim_background, close_only=self.close_only)
|
|
221
225
|
self._overlay.next_requested.connect(self.next)
|
|
222
226
|
self._overlay.back_requested.connect(self.back)
|
|
223
227
|
self._overlay.exit_requested.connect(self.stop)
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
from math import ceil
|
|
5
5
|
|
|
6
6
|
from PySide6.QtCore import QPoint, QRect, QRectF, Qt, Signal
|
|
7
|
-
from PySide6.QtGui import QPainter, QPainterPath, QPalette, QPen
|
|
7
|
+
from PySide6.QtGui import QColor, QPainter, QPainterPath, QPalette, QPen
|
|
8
8
|
from PySide6.QtWidgets import (
|
|
9
9
|
QFrame, QHBoxLayout, QLabel, QPushButton, QSizePolicy, QTextBrowser,
|
|
10
10
|
QVBoxLayout, QWidget,
|
|
@@ -19,9 +19,10 @@ class TutorialOverlay(QWidget):
|
|
|
19
19
|
back_requested = Signal()
|
|
20
20
|
exit_requested = Signal()
|
|
21
21
|
|
|
22
|
-
def __init__(self, host: QWidget, *, dim_background: bool = True):
|
|
22
|
+
def __init__(self, host: QWidget, *, dim_background: bool = True, close_only: bool = False):
|
|
23
23
|
super().__init__(host)
|
|
24
24
|
self.dim_background = dim_background
|
|
25
|
+
self.close_only = close_only
|
|
25
26
|
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
|
|
26
27
|
self.hole = QRect()
|
|
27
28
|
self.step: TutorialStep | None = None
|
|
@@ -48,17 +49,40 @@ class TutorialOverlay(QWidget):
|
|
|
48
49
|
self.body.setFrameShape(QFrame.Shape.NoFrame)
|
|
49
50
|
self.body.setOpenExternalLinks(False)
|
|
50
51
|
self.body.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
if close_only:
|
|
53
|
+
self.counter.setMinimumWidth(0)
|
|
54
|
+
self.counter.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Preferred)
|
|
55
|
+
header = QHBoxLayout()
|
|
56
|
+
header.setContentsMargins(0, 0, 0, 0)
|
|
57
|
+
header.addWidget(self.counter, 1)
|
|
58
|
+
layout.addLayout(header)
|
|
59
|
+
else:
|
|
60
|
+
layout.addWidget(self.counter)
|
|
61
|
+
layout.addWidget(self.title)
|
|
62
|
+
layout.addWidget(self.body)
|
|
53
63
|
actions = QHBoxLayout()
|
|
54
64
|
self.exit_button = QPushButton(self.tr("Exit · Esc"))
|
|
55
65
|
self.back_button = QPushButton(self.tr("Back"))
|
|
56
66
|
self.next_button = QPushButton(self.tr("Next"))
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
if close_only:
|
|
68
|
+
self.exit_button.setText("×")
|
|
69
|
+
self.exit_button.setAccessibleName(self.tr("Close tutorial"))
|
|
70
|
+
self.exit_button.setToolTip(self.tr("Close tutorial (Esc)"))
|
|
71
|
+
self.exit_button.setFlat(True)
|
|
72
|
+
self.exit_button.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
|
|
73
|
+
self.exit_button.setFixedSize(28, 28)
|
|
74
|
+
self.exit_button.setStyleSheet("font-size: 20px; padding: 0;")
|
|
75
|
+
header.addWidget(self.exit_button, 0, Qt.AlignmentFlag.AlignTop)
|
|
76
|
+
self.back_button.setParent(self.panel)
|
|
77
|
+
self.next_button.setParent(self.panel)
|
|
78
|
+
self.back_button.hide()
|
|
79
|
+
self.next_button.hide()
|
|
80
|
+
else:
|
|
81
|
+
for button in (self.exit_button, self.back_button, self.next_button):
|
|
82
|
+
button.setMinimumWidth(0)
|
|
83
|
+
button.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Fixed)
|
|
84
|
+
actions.addWidget(button)
|
|
85
|
+
layout.addLayout(actions)
|
|
62
86
|
self.exit_button.clicked.connect(self.exit_requested)
|
|
63
87
|
self.back_button.clicked.connect(self.back_requested)
|
|
64
88
|
self.next_button.clicked.connect(self.next_requested)
|
|
@@ -147,7 +171,7 @@ class TutorialOverlay(QWidget):
|
|
|
147
171
|
self.update()
|
|
148
172
|
|
|
149
173
|
def focus_guide(self):
|
|
150
|
-
(self.next_button if self.next_button.isEnabled() else self.exit_button).setFocus()
|
|
174
|
+
(self.next_button if not self.close_only and self.next_button.isEnabled() else self.exit_button).setFocus()
|
|
151
175
|
|
|
152
176
|
def paintEvent(self, event):
|
|
153
177
|
painter = QPainter(self)
|
|
@@ -160,5 +184,14 @@ class TutorialOverlay(QWidget):
|
|
|
160
184
|
opening = QPainterPath()
|
|
161
185
|
opening.addRect(QRectF(self.hole))
|
|
162
186
|
painter.fillPath(path.subtracted(opening), shade)
|
|
163
|
-
|
|
164
|
-
|
|
187
|
+
# A two-tone ring distinguishes the guide from the theme's selection and
|
|
188
|
+
# button colors. The contrasting outer stroke keeps it visible over mixed
|
|
189
|
+
# surfaces, including selected controls and application artwork.
|
|
190
|
+
dark = self.palette().color(QPalette.ColorRole.Window).lightness() < 128
|
|
191
|
+
halo = QColor("#141a22" if dark else "#ffffff")
|
|
192
|
+
guide = QColor("#ffd166" if dark else "#8c4b00")
|
|
193
|
+
rect = QRectF(self.hole.adjusted(-5, -5, 5, 5))
|
|
194
|
+
painter.setPen(QPen(halo, 7))
|
|
195
|
+
painter.drawRoundedRect(rect, 7, 7)
|
|
196
|
+
painter.setPen(QPen(guide, 3))
|
|
197
|
+
painter.drawRoundedRect(rect, 7, 7)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ms_components
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: PySide6 UI components for MolSuite: smart table, project browser, job monitor, PyMOL dock, steppers.
|
|
5
5
|
Author: Mario S. Valdés-Tresanco, Mario E. Valdés-Tresanco
|
|
6
6
|
License-Expression: MIT
|
|
@@ -154,3 +154,23 @@ def test_a_window_stays_a_window_on_double_click_and_drop(app):
|
|
|
154
154
|
|
|
155
155
|
window.close()
|
|
156
156
|
app.processEvents()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_action_separator_sits_by_order_and_survives_a_rebuild(app):
|
|
160
|
+
from ms_components.ms_dockwidget.widget import ToolbarSeparator
|
|
161
|
+
|
|
162
|
+
window = QMainWindow()
|
|
163
|
+
manager = DockManager(window)
|
|
164
|
+
manager.add_action_button("a", region=Region.BOTTOM_LEFT, order=1, on_click=lambda: None)
|
|
165
|
+
manager.add_action_button("b", region=Region.BOTTOM_LEFT, order=3, on_click=lambda: None)
|
|
166
|
+
manager.add_action_separator("line", region=Region.BOTTOM_LEFT, order=2)
|
|
167
|
+
manager.set_show_tool_names(True) # restyles every button: the separator is not one
|
|
168
|
+
manager._build_toolbars()
|
|
169
|
+
|
|
170
|
+
layout = manager.left_toolbar.layout_for_region(Region.BOTTOM_LEFT)
|
|
171
|
+
widgets = [layout.itemAt(i).widget() for i in range(layout.count())]
|
|
172
|
+
assert widgets[1] is manager.action_separators["line"]["button"]
|
|
173
|
+
assert isinstance(widgets[1], ToolbarSeparator)
|
|
174
|
+
assert widgets[0] is manager.action_buttons["a"]["button"]
|
|
175
|
+
assert widgets[2] is manager.action_buttons["b"]["button"]
|
|
176
|
+
window.close()
|
|
@@ -157,6 +157,22 @@ def test_outline_only_presentation_preserves_the_background(ui):
|
|
|
157
157
|
assert QApplication.widgetAt(button.mapToGlobal(button.rect().center())) is button
|
|
158
158
|
|
|
159
159
|
|
|
160
|
+
def test_guide_outline_changes_with_theme_and_keeps_target_clickable(ui):
|
|
161
|
+
app, window, button, other, controller = ui
|
|
162
|
+
controller.dim_background = False
|
|
163
|
+
controller.start(tour(interactive=True))
|
|
164
|
+
for theme, expected in (("github_light", "#8c4b00"), ("github_dark", "#ffd166")):
|
|
165
|
+
apply_theme(theme, app)
|
|
166
|
+
app.processEvents()
|
|
167
|
+
image = window.grab().toImage()
|
|
168
|
+
rect = controller.overlay.hole.adjusted(-9, -9, 9, 9).intersected(window.rect())
|
|
169
|
+
colors = {image.pixelColor(x, y).name()
|
|
170
|
+
for x in range(rect.left(), rect.right() + 1)
|
|
171
|
+
for y in range(rect.top(), rect.bottom() + 1)}
|
|
172
|
+
assert expected in colors
|
|
173
|
+
assert QApplication.widgetAt(button.mapToGlobal(button.rect().center())) is button
|
|
174
|
+
|
|
175
|
+
|
|
160
176
|
def test_accepting_a_dialog_keeps_the_tutorial_active_but_closing_cancels(ui):
|
|
161
177
|
app, window, button, other, controller = ui
|
|
162
178
|
dialog = QDialog(window)
|
|
@@ -458,3 +474,55 @@ def test_a_still_tour_does_not_repaint_on_every_tracker_tick(ui):
|
|
|
458
474
|
QTest.qWait(800) # ten tracker ticks
|
|
459
475
|
controller.overlay.removeEventFilter(counter)
|
|
460
476
|
assert len(paints) <= 1
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def test_close_only_mode_has_accessible_close_control_and_escape(ui):
|
|
480
|
+
app, _window, button, _other, controller = ui
|
|
481
|
+
controller.close_only = True
|
|
482
|
+
tutorial = Tutorial("interactive", "Interactive", (
|
|
483
|
+
TutorialStep("action", "run", "Action", "Click the action.", "clicked"),
|
|
484
|
+
))
|
|
485
|
+
controller.start(tutorial)
|
|
486
|
+
overlay = controller.overlay
|
|
487
|
+
assert overlay.exit_button.text() == "×"
|
|
488
|
+
assert overlay.exit_button.accessibleName() == "Close tutorial"
|
|
489
|
+
assert overlay.exit_button.isVisible()
|
|
490
|
+
assert not overlay.back_button.isVisible() and not overlay.next_button.isVisible()
|
|
491
|
+
assert overlay.exit_button.geometry().right() > overlay.counter.geometry().right()
|
|
492
|
+
assert overlay.panel.rect().contains(overlay.exit_button.geometry())
|
|
493
|
+
QTest.mouseClick(overlay.exit_button, Qt.LeftButton)
|
|
494
|
+
assert not controller.is_active
|
|
495
|
+
controller.start(tutorial)
|
|
496
|
+
QTest.keyClick(controller.overlay.exit_button, Qt.Key_Escape)
|
|
497
|
+
assert not controller.is_active
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def test_close_only_rejects_steps_that_need_next_button(ui):
|
|
501
|
+
_app, _window, _button, _other, controller = ui
|
|
502
|
+
controller.close_only = True
|
|
503
|
+
with pytest.raises(ValueError, match="require an event"):
|
|
504
|
+
controller.start(tour())
|
|
505
|
+
assert not controller.is_active
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def test_close_only_follows_target_into_another_window(ui):
|
|
509
|
+
app, window, button, _other, controller = ui
|
|
510
|
+
dialog = QDialog(window)
|
|
511
|
+
action = QPushButton("Finish", dialog)
|
|
512
|
+
button.clicked.connect(dialog.show)
|
|
513
|
+
controller.targets["dialog"] = TutorialTarget(action)
|
|
514
|
+
controller.events["finish"] = TutorialEvent(action.clicked)
|
|
515
|
+
controller.close_only = True
|
|
516
|
+
controller.start(Tutorial("dialog", "Dialog", (
|
|
517
|
+
TutorialStep("open", "run", "Open", "Open dialog.", "clicked"),
|
|
518
|
+
TutorialStep("finish", "dialog", "Finish", "Finish the task.", "finish"),
|
|
519
|
+
)))
|
|
520
|
+
QTest.mouseClick(button, Qt.LeftButton)
|
|
521
|
+
app.processEvents()
|
|
522
|
+
overlay = controller.overlay
|
|
523
|
+
assert overlay.parentWidget() is dialog
|
|
524
|
+
assert overlay.exit_button.isVisible() and overlay.exit_button.text() == "×"
|
|
525
|
+
assert overlay.panel.rect().contains(overlay.exit_button.geometry())
|
|
526
|
+
QTest.mouseClick(overlay.exit_button, Qt.LeftButton)
|
|
527
|
+
assert not controller.is_active
|
|
528
|
+
dialog.close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_dockwidget/resources/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_pymol/icons/hydrogens-polar.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/pagination_control.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ms_components-0.4.0 → ms_components-0.4.2}/src/ms_components/ms_table/test_external_filters.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|