From daa896866ff7987088bd9bab462bb0e22bdb991f Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:39:10 +0200 Subject: [PATCH] [VDD] Defer heavy construction until after the tab paints (#7115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [VDD] Defer heavy construction until after the tab paints * Use singleshot QTimer instead of member variable. Took 27 minutes --------- Co-authored-by: Lukas BrĂ¼bach --- .../visual_database_display_widget.cpp | 58 ++++++++++++++----- .../visual_database_display_widget.h | 5 +- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index dc98e6940..0cdf60d5d 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -140,9 +141,6 @@ void VisualDatabaseDisplayWidget::initialize() { databaseLoadIndicator->setVisible(false); - filterContainer->initialize(); - filterContainer->setVisible(true); - searchContainer->addWidget(colorFilterWidget); searchContainer->addWidget(clearFilterWidget); searchContainer->addWidget(searchEdit); @@ -158,17 +156,43 @@ void VisualDatabaseDisplayWidget::initialize() mainLayout->addWidget(cardSizeWidget); - databaseDisplayModel->setFilterTree(filterModel->filterTree()); - connect(filterModel, &FilterTreeModel::layoutChanged, this, &VisualDatabaseDisplayWidget::onSearchModelChanged); - loadCardsTimer = new QTimer(this); - loadCardsTimer->setSingleShot(true); // Ensure it only fires once after the timeout + initializeFilters(); +} - connect(loadCardsTimer, &QTimer::timeout, this, [this]() { loadCurrentPage(); }); - loadCardsTimer->start(5000); +void VisualDatabaseDisplayWidget::initializeFilters() +{ + if (filtersInitialized || !isVisible() || CardDatabaseManager::getInstance()->getLoadStatus() != LoadStatus::Ok) { + return; + } - retranslateUi(); + filtersInitialized = true; + + // The filter toolbar builds its widgets by iterating the entire card database + // (per-set, per-main-type, per-sub-type and per-format buttons). Building it + // inside showEvent would block the tab switch, so keep it hidden and defer the + // build to the next event loop turn, letting the tab paint first. The toolbar + // then appears one event loop turn later, shifting the grid down by the toolbar + // height -- the intended tradeoff of an responsive tab switch. + filterContainer->setVisible(false); + + QTimer::singleShot(0, this, [this] { + filterContainer->initialize(); + filterContainer->setVisible(true); + + databaseDisplayModel->setFilterTree(filterModel->filterTree()); + + QTimer::singleShot(5000, this, [this] { loadCurrentPage(); }); + + retranslateUi(); + }); +} + +void VisualDatabaseDisplayWidget::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + initializeFilters(); } void VisualDatabaseDisplayWidget::retranslateUi() @@ -292,9 +316,17 @@ void VisualDatabaseDisplayWidget::loadCurrentPage() { // Ensure only the initial page is loaded if (currentPage == 0) { - // Only load the first page initially - qCDebug(VisualDatabaseDisplayLog) << "Loading the first page"; - populateCards(); + if (!initialLoadScheduled) { + initialLoadScheduled = true; + qCDebug(VisualDatabaseDisplayLog) << "Loading the first page"; + // Defer the first page so the tab switch stays responsive. The card + // grid builds one event loop turn later. This also applies to + // search-driven reloads, which reset currentPage back to 0. + QTimer::singleShot(0, this, [this] { + initialLoadScheduled = false; + populateCards(); + }); + } } else if (nearEndOfPage()) { // If not the first page, just load the next page and append to the flow widget loadNextPage(); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index a383e8ead..6e4d87876 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -115,17 +115,20 @@ private: OverlapControlWidget *overlapControlWidget; CardSizeWidget *cardSizeWidget; QTimer *debounceTimer; - QTimer *loadCardsTimer; int debounceTime = 300; // in Ms int currentPage = 0; // Current page index int cardsPerPage = 100; // Number of cards per page + bool filtersInitialized = false; + bool initialLoadScheduled = false; + void initializeFilters(); void highlightAllSearchEdit(); bool nearEndOfPage() const; protected: void resizeEvent(QResizeEvent *event) override; + void showEvent(QShowEvent *event) override; }; #endif // VISUAL_DATABASE_DISPLAY_WIDGET_H