Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions quantui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,13 @@ class QuantUIApp:
past_dd: Any
past_output: Any
past_refresh_btn: Any
history_search: Any
history_filter_clear_btn: Any
history_count_lbl: Any
history_method_dd: Any
history_basis_dd: Any
history_date_from: Any
history_date_to: Any
lib_category_dd: Any
lib_search_txt: Any
lib_results_dd: Any
Expand Down Expand Up @@ -1788,6 +1795,21 @@ def _wire_callbacks(self) -> None:
self.past_refresh_btn.on_click(self._on_past_refresh)
self.copy_path_btn.on_click(self._on_copy_results_path)
self.view_log_btn.on_click(self._on_view_log)
# History search / faceted filters (HIST.7)
for _w in (
self.history_search,
self.history_method_dd,
self.history_basis_dd,
self.history_date_from,
self.history_date_to,
):
_w.observe(self._safe_cb(self._on_history_filter_changed), names="value")
for _chip in (
*self._history_calc_chips.values(),
*self._history_status_chips.values(),
):
_chip.observe(self._safe_cb(self._on_history_filter_changed), names="value")
self.history_filter_clear_btn.on_click(self._on_history_filter_clear)
# Perf stats reset
self._reset_btn.on_click(self._on_reset_click)
self._reset_confirm_yes.on_click(self._on_confirm_yes)
Expand Down Expand Up @@ -3512,6 +3534,32 @@ def _on_compare_clear(self, btn) -> None:
def _on_past_dd_changed(self, change) -> None:
_hist_on_past_dd_changed(self, change, layout_fn=_layout)

def _on_history_filter_changed(self, change=None) -> None:
from quantui.app_history import apply_history_filter

apply_history_filter(self)

def _on_history_filter_clear(self, btn=None) -> None:
from quantui.app_history import apply_history_filter

# Reset every facet widget, suspending the observer so we run a single
# filter pass at the end instead of one per widget reset.
self._history_filter_suspend = True
try:
self.history_search.value = ""
self.history_method_dd.value = ""
self.history_basis_dd.value = ""
self.history_date_from.value = None
self.history_date_to.value = None
for chip in (
*self._history_calc_chips.values(),
*self._history_status_chips.values(),
):
chip.value = False
finally:
self._history_filter_suspend = False
apply_history_filter(self)

def _on_past_refresh(self, btn) -> None:
self._activity_begin("Refreshing history list...")
try:
Expand Down
103 changes: 102 additions & 1 deletion quantui/app_builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,15 +430,116 @@ def build_history_section(
app._cal_accordion = widgets.Accordion(children=[cal_panel], selected_index=None)
app._cal_accordion.set_title(0, "Calibrate time estimates")

# ── Search / faceted filters (HIST.7) ──────────────────────────────
# All filtering is client-side over the cached ``app._history_entries``
# list; widgets here only hold facet state. See app_history.apply_history_filter.
from quantui.app_history import HISTORY_CALC_TYPE_FACETS, HISTORY_STATUS_FACETS

app._history_entries = []
app._history_filter_suspend = False
app.history_search = widgets.Text(
placeholder="search name or formula (e.g. benzene, C6H6)",
continuous_update=True, # type-to-narrow
layout=layout_fn(width="300px"),
)
app.history_filter_clear_btn = widgets.Button(
icon="times",
tooltip="Clear all history filters",
layout=layout_fn(width="40px"),
)
app.history_count_lbl = widgets.HTML(
'<span style="color:#888;font-size:12px"></span>'
)
app._history_calc_chips = {
key: widgets.ToggleButton(
value=False,
description=label,
tooltip=f"Show only {label} calculations",
layout=layout_fn(width="auto"),
)
for label, key in HISTORY_CALC_TYPE_FACETS
}
app.history_method_dd = widgets.Dropdown(
options=[("Any method", "")],
value="",
description="Method:",
style={"description_width": "55px"},
layout=layout_fn(width="200px"),
)
app.history_basis_dd = widgets.Dropdown(
options=[("Any basis", "")],
value="",
description="Basis:",
style={"description_width": "55px"},
layout=layout_fn(width="200px"),
)
app.history_date_from = widgets.DatePicker(
description="From:",
style={"description_width": "45px"},
layout=layout_fn(width="200px"),
)
app.history_date_to = widgets.DatePicker(
description="To:",
style={"description_width": "35px"},
layout=layout_fn(width="190px"),
)
app._history_status_chips = {
key: widgets.ToggleButton(
value=False,
description=label,
layout=layout_fn(width="auto"),
)
for label, key in HISTORY_STATUS_FACETS
}

def _facet_label(text: str, width: str = "60px") -> widgets.HTML:
return widgets.HTML(
f'<span style="color:#555;font-size:12px;width:{width};'
f'display:inline-block">{text}</span>'
)

app._history_filter_box = widgets.VBox(
[
widgets.HBox(
[
app.history_search,
app.history_filter_clear_btn,
app.history_count_lbl,
],
layout=layout_fn(align_items="center", gap="6px"),
),
widgets.HBox(
[_facet_label("Type:"), *app._history_calc_chips.values()],
layout=layout_fn(align_items="center", gap="4px", flex_wrap="wrap"),
),
widgets.HBox(
[app.history_method_dd, app.history_basis_dd],
layout=layout_fn(align_items="center", gap="8px"),
),
widgets.HBox(
[
app.history_date_from,
app.history_date_to,
_facet_label("Status:", "55px"),
*app._history_status_chips.values(),
],
layout=layout_fn(align_items="center", gap="6px", flex_wrap="wrap"),
),
],
layout=layout_fn(margin="0 0 8px", gap="4px"),
)

# The History tab is now purely the result-browser. Performance stats
# + Calibrate accordions moved to the System Settings tab — see below —
# so the user finds benchmarking + system state in one logical place.
app.history_panel = widgets.VBox(
[
widgets.HTML(
'<p style="color:#555;font-size:13px;margin:0 0 8px">'
"Calculations are saved automatically. Select one below to view its results.</p>"
"Calculations are saved automatically. Filter below, then select "
"one to view its results.</p>"
),
app._history_filter_box,
widgets.HBox(
[
app.past_dd,
Expand Down
Loading
Loading