Skip to content

Commit 0ea48cc

Browse files
committed
Loading indicator for databases on project change
1 parent 0779c6d commit 0ea48cc

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

activity_browser/bwutils/metadata/loader.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
import pickle
55
from logging import getLogger
6+
from typing import Literal
67

78
import pandas as pd
89
import bw2data as bd
@@ -20,6 +21,9 @@
2021

2122

2223
class MDSLoader(QtCore.QObject):
24+
primary_status: Literal["idle", "loading", "done"] = "idle"
25+
secondary_status: Literal["idle", "loading", "done"] = "idle"
26+
2327
def __init__(self, mds: MetaDataStore):
2428
super().__init__(mds)
2529
self.moveToThread(application.thread())
@@ -34,6 +38,10 @@ def on_project_changed(self):
3438
self.load_project()
3539

3640
def load_project(self):
41+
# set statuses
42+
self.primary_status = "loading"
43+
self.secondary_status = "loading"
44+
3745
# start loading threads
3846
thread = SecondaryLoadThread(self)
3947
thread.done.connect(self.secondary_load_project)
@@ -55,6 +63,8 @@ def primary_load_project(self):
5563

5664
for idx in primary_df.index:
5765
self.mds.register_mutation(idx, "add")
66+
67+
self.primary_status = "done"
5868

5969
def secondary_load_project(self, secondary_df: pd.DataFrame, sqlite_db: str):
6070
if sqlite_db != str(sqlite3_lci_db._filepath):
@@ -66,6 +76,8 @@ def secondary_load_project(self, secondary_df: pd.DataFrame, sqlite_db: str):
6676

6777
for idx in secondary_df.index:
6878
self.mds.register_mutation(idx, "update")
79+
80+
self.secondary_status = "done"
6981

7082
def load_database(self, database_name: str):
7183
# start loading threads

activity_browser/layouts/panes/database_products.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,48 @@ def __init__(self, parent, db_name: str):
6161
self.search.setMaximumHeight(30)
6262
self.search.setPlaceholderText("Quick Search")
6363

64+
# Create loading indicator with spinner
65+
self.loading_spinner = QtWidgets.QProgressBar()
66+
self.loading_spinner.setRange(0, 0) # Indeterminate/busy indicator
67+
self.loading_spinner.setTextVisible(False)
68+
self.loading_spinner.setMaximumWidth(200)
69+
self.loading_spinner.setMaximumHeight(20)
70+
71+
self.loading_label = widgets.ABLabel("Loading database...")
72+
self.loading_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
73+
font = self.loading_label.font()
74+
font.setPointSize(14)
75+
self.loading_label.setFont(font)
76+
self.loading_label.setStyleSheet("color: gray; padding: 10px;")
77+
6478
self.build_layout()
6579
self.connect_signals()
80+
self.update_loading_state()
6681

6782
def build_layout(self):
68-
table_layout = QtWidgets.QHBoxLayout()
83+
# Create a stacked layout to switch between loading and table view
84+
self.stacked_layout = QtWidgets.QStackedLayout()
85+
86+
# Page 0: Loading indicator with spinner
87+
loading_widget = QtWidgets.QWidget()
88+
loading_layout = QtWidgets.QVBoxLayout(loading_widget)
89+
loading_layout.addStretch()
90+
loading_layout.addWidget(self.loading_spinner, alignment=Qt.AlignmentFlag.AlignCenter)
91+
loading_layout.addWidget(self.loading_label)
92+
loading_layout.addStretch()
93+
self.stacked_layout.addWidget(loading_widget)
94+
95+
# Page 1: Table view
96+
table_widget = QtWidgets.QWidget()
97+
table_layout = QtWidgets.QVBoxLayout(table_widget)
6998
table_layout.setSpacing(0)
99+
table_layout.setContentsMargins(0, 0, 0, 0)
70100
table_layout.addWidget(self.table_view)
101+
self.stacked_layout.addWidget(table_widget)
71102

72103
layout = QtWidgets.QVBoxLayout(self)
73104
layout.addWidget(self.search)
74-
layout.addLayout(table_layout)
105+
layout.addLayout(self.stacked_layout)
75106

76107
# Set the table view as the central widget of the window
77108
self.setLayout(layout)
@@ -84,9 +115,24 @@ def connect_signals(self):
84115
self.search.textChangedDebounce.connect(self.table_view.setAllFilter)
85116

86117
def on_metadata_changed(self, added, updated, deleted):
118+
# Check if primary data has finished loading
119+
self.update_loading_state()
120+
87121
if any(db == self.database.name for db, code in added | updated | deleted):
88122
self.sync()
89123

124+
def update_loading_state(self):
125+
"""
126+
Updates the loading state based on whether primary metadata has loaded.
127+
Shows the loading indicator if primary data is still loading, otherwise shows the table.
128+
"""
129+
if AB_metadata.loader.secondary_status == "done":
130+
# Show table view
131+
self.stacked_layout.setCurrentIndex(1)
132+
else:
133+
# Show loading indicator
134+
self.stacked_layout.setCurrentIndex(0)
135+
90136
def sync(self):
91137
"""
92138
Synchronizes the widget with the current state of the database.

0 commit comments

Comments
 (0)