From bca8ce94239ab28f8d989967b7783404af3e07df Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 19 Nov 2023 23:50:59 -0500 Subject: [PATCH] Wire up Poll notification GUI machinery to signals Also address wallet restart with existing current polls. --- src/qt/bitcoingui.cpp | 35 ++++++++++++++++++++++---------- src/qt/bitcoingui.h | 1 + src/qt/voting/pollcardview.cpp | 10 ++++----- src/qt/voting/pollcardview.h | 2 +- src/qt/voting/polltab.cpp | 34 +++++++++++++++---------------- src/qt/voting/polltab.h | 2 +- src/qt/voting/polltablemodel.cpp | 8 ++++---- src/qt/voting/polltablemodel.h | 2 +- src/qt/voting/votingpage.cpp | 11 ++++++++++ src/qt/voting/votingpage.h | 1 + 10 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index bd0b96456f..aa7c86315f 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -20,6 +20,7 @@ #include "signverifymessagedialog.h" #include "optionsdialog.h" #include "aboutdialog.h" +#include "voting/polltab.h" #include "voting/votingpage.h" #include "clientmodel.h" #include "walletmodel.h" @@ -43,6 +44,7 @@ #include "univalue.h" #include "upgradeqt.h" #include "voting/votingmodel.h" +#include "voting/polltablemodel.h" #ifdef Q_OS_MAC #include "macdockiconhandler.h" @@ -1946,7 +1948,11 @@ void BitcoinGUI::extracted(QStringList& expiring_polls, QString& notification) void BitcoinGUI::handleExpiredPoll() { - if (!clientModel || !clientModel->getOptionsModel()) { + if (!clientModel) { + return; + } + + if (!clientModel->getOptionsModel()) { return; } @@ -1954,20 +1960,27 @@ void BitcoinGUI::handleExpiredPoll() return; } - if (!clientModel->getOptionsModel()->getDisablePollNotifications()) { - QStringList expiring_polls = votingModel->getExpiringPollsNotNotified(); + // Only do if in sync. + if (researcherModel && !researcherModel->outOfSync() && votingPage->getActiveTab()) { + + // First refresh the active poll tab and underlying table + votingPage->getActiveTab()->refresh(); - if (!expiring_polls.isEmpty()) { - QString notification = tr("The following poll(s) are about to expire:\n"); + if (!clientModel->getOptionsModel()->getDisablePollNotifications()) { + QStringList expiring_polls = votingModel->getExpiringPollsNotNotified(); - extracted(expiring_polls, notification); + if (!expiring_polls.isEmpty()) { + QString notification = tr("The following poll(s) are about to expire:\n"); - notification += tr("Open Gridcoin to vote."); + extracted(expiring_polls, notification); - notificator->notify( - Notificator::Information, - tr("Poll(s) about to expire"), - notification); + notification += tr("Open Gridcoin to vote."); + + notificator->notify( + Notificator::Information, + tr("Poll(s) about to expire"), + notification); + } } } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index adbd9216e9..5b1413cbbf 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -20,6 +20,7 @@ class WalletModel; class ResearcherModel; class MRCModel; class VotingModel; +class PollTableModel; class TransactionView; class OverviewPage; class FavoritesPage; diff --git a/src/qt/voting/pollcardview.cpp b/src/qt/voting/pollcardview.cpp index 6c1e7798b3..c720183851 100644 --- a/src/qt/voting/pollcardview.cpp +++ b/src/qt/voting/pollcardview.cpp @@ -33,7 +33,7 @@ PollCardView::~PollCardView() void PollCardView::setModel(PollTableModel* model) { - m_model = model; + m_polltable_model = model; if (!model) { return; @@ -41,7 +41,7 @@ void PollCardView::setModel(PollTableModel* model) connect(model, &PollTableModel::layoutChanged, this, &PollCardView::redraw); - if (!m_refresh_timer && m_model->includesActivePolls()) { + if (!m_refresh_timer && m_polltable_model->includesActivePolls()) { m_refresh_timer.reset(new QTimer(this)); m_refresh_timer->setTimerType(Qt::VeryCoarseTimer); @@ -76,15 +76,15 @@ void PollCardView::redraw() // sorting and filtering. Hook up model events for these operations. clear(); - if (!m_model) { + if (!m_polltable_model) { return; } const QDateTime now = QDateTime::currentDateTimeUtc(); const QModelIndex dummy_parent; - for (int i = 0; i < m_model->rowCount(dummy_parent); ++i) { - if (const PollItem* poll_item = m_model->rowItem(i)) { + for (int i = 0; i < m_polltable_model->rowCount(dummy_parent); ++i) { + if (const PollItem* poll_item = m_polltable_model->rowItem(i)) { PollCard* card = new PollCard(*poll_item, this); card->updateRemainingTime(now); card->updateIcons(m_theme); diff --git a/src/qt/voting/pollcardview.h b/src/qt/voting/pollcardview.h index d85efa6503..58da557f7f 100644 --- a/src/qt/voting/pollcardview.h +++ b/src/qt/voting/pollcardview.h @@ -43,7 +43,7 @@ public slots: private: Ui::PollCardView* ui; - PollTableModel* m_model; + PollTableModel* m_polltable_model; std::unique_ptr m_refresh_timer; QString m_theme; diff --git a/src/qt/voting/polltab.cpp b/src/qt/voting/polltab.cpp index d08d9b1e26..10f5ffb83e 100644 --- a/src/qt/voting/polltab.cpp +++ b/src/qt/voting/polltab.cpp @@ -134,7 +134,7 @@ private slots: PollTab::PollTab(QWidget* parent) : QWidget(parent) , ui(new Ui::PollTab) - , m_model(new PollTableModel(this)) + , m_polltable_model(new PollTableModel(this)) , m_no_result(new NoResult(this)) , m_loading(new LoadingBar(this)) { @@ -152,7 +152,7 @@ PollTab::PollTab(QWidget* parent) connect(ui->cards, &PollCardView::detailsRequested, this, &PollTab::showDetailsRowDialog); connect(ui->table, &QAbstractItemView::doubleClicked, this, &PollTab::showPreferredDialog); connect(ui->table, &QWidget::customContextMenuRequested, this, &PollTab::showTableContextMenu); - connect(m_model.get(), &PollTableModel::layoutChanged, this, &PollTab::finishRefresh); + connect(m_polltable_model.get(), &PollTableModel::layoutChanged, this, &PollTab::finishRefresh); } PollTab::~PollTab() @@ -163,15 +163,15 @@ PollTab::~PollTab() void PollTab::setVotingModel(VotingModel* model) { m_voting_model = model; - m_model->setModel(model); + m_polltable_model->setModel(model); - ui->cards->setModel(m_model.get()); - ui->table->setModel(m_model.get()); + ui->cards->setModel(m_polltable_model.get()); + ui->table->setModel(m_polltable_model.get()); } void PollTab::setPollFilterFlags(PollFilterFlag flags) { - m_model->setPollFilterFlags(flags); + m_polltable_model->setPollFilterFlags(flags); } void PollTab::changeViewMode(const ViewId view_id) @@ -181,26 +181,26 @@ void PollTab::changeViewMode(const ViewId view_id) void PollTab::refresh() { - if (m_model->empty()) { + if (m_polltable_model->empty()) { m_no_result->showDefaultLoadingTitle(); m_no_result->contentWidgetAs()->setText(WaitMessage()); } m_loading->start(); - m_model->refresh(); + m_polltable_model->refresh(); } void PollTab::filter(const QString& needle) { if (needle != m_last_filter) { - m_model->changeTitleFilter(needle); + m_polltable_model->changeTitleFilter(needle); m_last_filter = needle; } } void PollTab::sort(const int column) { - const Qt::SortOrder order = m_model->sort(column); + const Qt::SortOrder order = m_polltable_model->sort(column); ui->table->horizontalHeader()->setSortIndicator(column, order); } @@ -215,7 +215,7 @@ const PollItem* PollTab::selectedTableItem() const return nullptr; } - return m_model->rowItem( + return m_polltable_model->rowItem( ui->table->selectionModel()->selectedIndexes().first().row()); } @@ -228,10 +228,10 @@ void PollTab::resizeEvent(QResizeEvent* event) void PollTab::finishRefresh() { m_loading->finish(); - ui->stack->setVisible(!m_model->empty()); - m_no_result->setVisible(m_model->empty()); + ui->stack->setVisible(!m_polltable_model->empty()); + m_no_result->setVisible(m_polltable_model->empty()); - if (m_model->empty()) { + if (m_polltable_model->empty()) { m_no_result->showDefaultNoResultTitle(); m_no_result->contentWidgetAs()->setText(FullRefreshMessage()); } @@ -239,7 +239,7 @@ void PollTab::finishRefresh() void PollTab::showVoteRowDialog(int row) { - if (const PollItem* const poll_item = m_model->rowItem(row)) { + if (const PollItem* const poll_item = m_polltable_model->rowItem(row)) { showVoteDialog(*poll_item); } } @@ -251,7 +251,7 @@ void PollTab::showVoteDialog(const PollItem& poll_item) void PollTab::showDetailsRowDialog(int row) { - if (const PollItem* const poll_item = m_model->rowItem(row)) { + if (const PollItem* const poll_item = m_polltable_model->rowItem(row)) { showDetailsDialog(*poll_item); } } @@ -263,7 +263,7 @@ void PollTab::showDetailsDialog(const PollItem& poll_item) void PollTab::showPreferredDialog(const QModelIndex& index) { - if (const PollItem* const poll_item = m_model->rowItem(index.row())) { + if (const PollItem* const poll_item = m_polltable_model->rowItem(index.row())) { if (poll_item->m_finished) { showDetailsDialog(*poll_item); } else { diff --git a/src/qt/voting/polltab.h b/src/qt/voting/polltab.h index 93e68252b4..8f333e0aad 100644 --- a/src/qt/voting/polltab.h +++ b/src/qt/voting/polltab.h @@ -60,7 +60,7 @@ public slots: private: Ui::PollTab* ui; VotingModel* m_voting_model; - std::unique_ptr m_model; + std::unique_ptr m_polltable_model; std::unique_ptr m_no_result; std::unique_ptr m_loading; QString m_last_filter; diff --git a/src/qt/voting/polltablemodel.cpp b/src/qt/voting/polltablemodel.cpp index 14f3bbe8ed..7a7c6d3f7e 100644 --- a/src/qt/voting/polltablemodel.cpp +++ b/src/qt/voting/polltablemodel.cpp @@ -212,11 +212,11 @@ PollTableModel::~PollTableModel() void PollTableModel::setModel(VotingModel* model) { - m_model = model; + m_voting_model = model; // Connect poll stale handler to newVoteReceived signal from voting model, which propagates // from the core. - connect(m_model, &VotingModel::newVoteReceived, this, &PollTableModel::handlePollStaleFlag); + connect(m_voting_model, &VotingModel::newVoteReceived, this, &PollTableModel::handlePollStaleFlag); } void PollTableModel::setPollFilterFlags(PollFilterFlag flags) @@ -254,13 +254,13 @@ const PollItem* PollTableModel::rowItem(int row) const void PollTableModel::refresh() { - if (!m_model || !m_refresh_mutex.tryLock()) { + if (!m_voting_model || !m_refresh_mutex.tryLock()) { return; } QtConcurrent::run([this]() { static_cast(m_data_model.get()) - ->reload(m_model->buildPollTable(m_filter_flags)); + ->reload(m_voting_model->buildPollTable(m_filter_flags)); m_refresh_mutex.unlock(); }); diff --git a/src/qt/voting/polltablemodel.h b/src/qt/voting/polltablemodel.h index 38620d3bab..1c9d0269b0 100644 --- a/src/qt/voting/polltablemodel.h +++ b/src/qt/voting/polltablemodel.h @@ -82,7 +82,7 @@ public slots: void handlePollStaleFlag(QString poll_txid_string); private: - VotingModel* m_model; + VotingModel* m_voting_model; std::unique_ptr m_data_model; GRC::PollFilterFlag m_filter_flags; QMutex m_refresh_mutex; diff --git a/src/qt/voting/votingpage.cpp b/src/qt/voting/votingpage.cpp index a592ee2576..52ab4de4f4 100644 --- a/src/qt/voting/votingpage.cpp +++ b/src/qt/voting/votingpage.cpp @@ -129,8 +129,15 @@ void VotingPage::setVotingModel(VotingModel* model) return; } + // Now that PollItem caching is available, automatically refresh current poll tab on receipt of new poll or vote. connect(model, &VotingModel::newPollReceived, [this]() { ui->pollReceivedLabel->show(); + currentTab().refresh(); + ui->pollReceivedLabel->hide(); + }); + + connect(model, &VotingModel::newVoteReceived, [this]() { + currentTab().refresh(); }); } @@ -149,6 +156,10 @@ PollTab& VotingPage::currentTab() return *qobject_cast(ui->tabWidget->currentWidget()); } +PollTab* VotingPage::getActiveTab() +{ + return m_tabs[0]; +} void VotingPage::updateIcons(const QString& theme) { m_filter_action->setIcon(QIcon(":/icons/" + theme + "_search")); diff --git a/src/qt/voting/votingpage.h b/src/qt/voting/votingpage.h index 93e7ce4b65..9ac6ab8b5e 100644 --- a/src/qt/voting/votingpage.h +++ b/src/qt/voting/votingpage.h @@ -35,6 +35,7 @@ class VotingPage : public QWidget void setOptionsModel(OptionsModel* model); PollTab& currentTab(); + PollTab* getActiveTab(); private: Ui::VotingPage* ui;