Skip to content

Commit

Permalink
Implement GUI machinery for poll expiry notification
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescowens committed Nov 19, 2023
1 parent 2b85fd2 commit b075021
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 14 deletions.
31 changes: 29 additions & 2 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1932,10 +1932,20 @@ void BitcoinGUI::handleNewPoll()
overviewPage->setCurrentPollTitle(votingModel->getCurrentPollTitle());
}

void BitcoinGUI::handleExpiredPoll()
//!
//! \brief BitcoinGUI::extracted. Helper function to avoid container detach on range loop warning.
//! \param expiring_polls
//! \param notification
//!
void BitcoinGUI::extracted(QStringList& expiring_polls, QString& notification)
{
// The only difference between this and handleNewPoll() is no call to the event notifier.
for (const auto& expiring_poll : expiring_polls) {
notification += expiring_poll + "\n";
}
}

void BitcoinGUI::handleExpiredPoll()
{
if (!clientModel || !clientModel->getOptionsModel()) {
return;
}
Expand All @@ -1944,6 +1954,23 @@ void BitcoinGUI::handleExpiredPoll()
return;
}

if (!clientModel->getOptionsModel()->getDisablePollNotifications()) {
QStringList expiring_polls = votingModel->getExpiringPollsNotNotified();

if (!expiring_polls.isEmpty()) {
QString notification = tr("The following poll(s) are about to expire:\n");

extracted(expiring_polls, notification);

notification += tr("Open Gridcoin to vote.");

notificator->notify(
Notificator::Information,
tr("Poll(s) about to expire"),
notification);
}
}

overviewPage->setCurrentPollTitle(votingModel->getCurrentPollTitle());
}

Expand Down
1 change: 1 addition & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ private slots:
QString GetEstimatedStakingFrequency(unsigned int nEstimateTime);

void handleNewPoll();
void extracted(QStringList& expiring_polls, QString& notification);
void handleExpiredPoll();
};

Expand Down
33 changes: 32 additions & 1 deletion src/qt/forms/optionsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,37 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="pollExpireNotifyLabel">
<property name="text">
<string>Hours before poll expiry reminder</string>
</property>
</widget>
</item>
<item>
<widget class="QValidatedLineEdit" name="pollExpireNotifyLineEdit">
<property name="toolTip">
<string>Valid values are between 0.25 and 24.0 hours.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_Window">
<property name="orientation">
Expand Down Expand Up @@ -585,7 +616,7 @@
<customwidget>
<class>QValidatedLineEdit</class>
<extends>QLineEdit</extends>
<header>qvalidatedlineedit.h</header>
<header location="global">qvalidatedlineedit.h</header>
</customwidget>
<customwidget>
<class>QValueComboBox</class>
Expand Down
86 changes: 77 additions & 9 deletions src/qt/optionsdialog.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "optionsdialog.h"
#include "qevent.h"
#include "ui_optionsdialog.h"

#include "netbase.h"
Expand All @@ -16,13 +17,16 @@
#include <QSystemTrayIcon>

OptionsDialog::OptionsDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::OptionsDialog)
, model(nullptr)
, mapper(nullptr)
, fRestartWarningDisplayed_Proxy(false)
, fRestartWarningDisplayed_Lang(false)
, fProxyIpValid(true)
: QDialog(parent)
, ui(new Ui::OptionsDialog)
, model(nullptr)
, mapper(nullptr)
, fRestartWarningDisplayed_Proxy(false)
, fRestartWarningDisplayed_Lang(false)
, fProxyIpValid(true)
, fStakingEfficiencyValid(true)
, fMinStakeSplitValueValid(true)
, fPollExpireNotifyValid(true)
{
ui->setupUi(this);

Expand All @@ -44,6 +48,7 @@ OptionsDialog::OptionsDialog(QWidget* parent)
ui->proxyIp->installEventFilter(this);
ui->stakingEfficiency->installEventFilter(this);
ui->minPostSplitOutputValue->installEventFilter(this);
ui->pollExpireNotifyLineEdit->installEventFilter(this);

/* Window elements init */
#ifdef Q_OS_MAC
Expand Down Expand Up @@ -103,17 +108,24 @@ OptionsDialog::OptionsDialog(QWidget* parent)
connect(this, &OptionsDialog::proxyIpValid, this, &OptionsDialog::handleProxyIpValid);
connect(this, &OptionsDialog::stakingEfficiencyValid, this, &OptionsDialog::handleStakingEfficiencyValid);
connect(this, &OptionsDialog::minStakeSplitValueValid, this, &OptionsDialog::handleMinStakeSplitValueValid);
/** setup/change UI elements when poll expiry notification time window is valid/invalid */
connect(this, &OptionsDialog::pollExpireNotifyValid, this, &OptionsDialog::handlePollExpireNotifyValid);

if (fTestNet) ui->disableUpdateCheck->setHidden(true);

ui->gridcoinAtStartupMinimised->setHidden(!ui->gridcoinAtStartup->isChecked());
ui->limitTxnDisplayDateEdit->setHidden(!ui->limitTxnDisplayCheckBox->isChecked());

ui->pollExpireNotifyLabel->setHidden(ui->disablePollNotifications->isChecked());
ui->pollExpireNotifyLineEdit->setHidden(ui->disablePollNotifications->isChecked());

connect(ui->gridcoinAtStartup, &QCheckBox::toggled, this, &OptionsDialog::hideStartMinimized);
connect(ui->gridcoinAtStartupMinimised, &QCheckBox::toggled, this, &OptionsDialog::hideStartMinimized);

connect(ui->limitTxnDisplayCheckBox, &QCheckBox::toggled, this, &OptionsDialog::hideLimitTxnDisplayDate);

connect(ui->disablePollNotifications, &QCheckBox::toggled, this , &OptionsDialog::hidePollExpireNotify);

bool stake_split_enabled = ui->enableStakeSplit->isChecked();

ui->stakingEfficiencyLabel->setHidden(!stake_split_enabled);
Expand Down Expand Up @@ -180,6 +192,7 @@ void OptionsDialog::setMapper()
/* Window */
mapper->addMapping(ui->disableTransactionNotifications, OptionsModel::DisableTrxNotifications);
mapper->addMapping(ui->disablePollNotifications, OptionsModel::DisablePollNotifications);
mapper->addMapping(ui->pollExpireNotifyLineEdit, OptionsModel::PollExpireNotification);
#ifndef Q_OS_MAC
if (QSystemTrayIcon::isSystemTrayAvailable()) {
mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
Expand All @@ -194,7 +207,7 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->styleComboBox, OptionsModel::WalletStylesheet,"currentData");
mapper->addMapping(ui->limitTxnDisplayCheckBox, OptionsModel::LimitTxnDisplay);
mapper->addMapping(ui->limitTxnDisplayDateEdit, OptionsModel::LimitTxnDate);
mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
}

void OptionsDialog::enableApplyButton()
Expand Down Expand Up @@ -298,6 +311,14 @@ void OptionsDialog::hideLimitTxnDisplayDate()
}
}

void OptionsDialog::hidePollExpireNotify()
{
if (model) {
ui->pollExpireNotifyLabel->setHidden(ui->disablePollNotifications->isChecked());
ui->pollExpireNotifyLineEdit->setHidden(ui->disablePollNotifications->isChecked());
}
}

void OptionsDialog::hideStakeSplitting()
{
if (model)
Expand Down Expand Up @@ -368,9 +389,40 @@ void OptionsDialog::handleMinStakeSplitValueValid(QValidatedLineEdit *object, bo
}
}

void OptionsDialog::handlePollExpireNotifyValid(QValidatedLineEdit *object, bool fState)
{
// this is used in a check before re-enabling the save buttons
fPollExpireNotifyValid = fState;

if (fPollExpireNotifyValid) {
enableSaveButtons();
ui->statusLabel->clear();
} else {
disableSaveButtons();
object->setValid(fPollExpireNotifyValid);
ui->statusLabel->setStyleSheet("QLabel { color: red; }");
ui->statusLabel->setText(tr("The supplied time for notification before poll expires must "
"be between 0.25 and 24 hours."));
}
}

bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusOut)
bool filter_event = false;

if (event->type() == QEvent::FocusOut) {
filter_event = true;
}

if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);

if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
filter_event = true;
}
}

if (filter_event)
{
if (object == ui->proxyIp)
{
Expand Down Expand Up @@ -423,6 +475,22 @@ bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
}
}
}

if (object == ui->pollExpireNotifyLineEdit) {
bool ok = false;
double hours = ui->pollExpireNotifyLineEdit->text().toDouble(&ok);

if (!ok) {
emit pollExpireNotifyValid(ui->pollExpireNotifyLineEdit, false);
} else {
if (hours >= 0.25 && hours <= 24.0) {
emit pollExpireNotifyValid(ui->pollExpireNotifyLineEdit, true);
} else {
emit pollExpireNotifyValid(ui->pollExpireNotifyLineEdit, false);
}
}
}
}

return QDialog::eventFilter(object, event);
}
4 changes: 4 additions & 0 deletions src/qt/optionsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,17 @@ private slots:
void hideStartMinimized();
void hideLimitTxnDisplayDate();
void hideStakeSplitting();
void hidePollExpireNotify();
void handleProxyIpValid(QValidatedLineEdit *object, bool fState);
void handleStakingEfficiencyValid(QValidatedLineEdit *object, bool fState);
void handleMinStakeSplitValueValid(QValidatedLineEdit *object, bool fState);
void handlePollExpireNotifyValid(QValidatedLineEdit *object, bool fState);

signals:
void proxyIpValid(QValidatedLineEdit *object, bool fValid);
void stakingEfficiencyValid(QValidatedLineEdit *object, bool fValid);
void minStakeSplitValueValid(QValidatedLineEdit *object, bool fValid);
void pollExpireNotifyValid(QValidatedLineEdit *object, bool fValid);

private:
Ui::OptionsDialog *ui;
Expand All @@ -65,6 +68,7 @@ private slots:
bool fProxyIpValid;
bool fStakingEfficiencyValid;
bool fMinStakeSplitValueValid;
bool fPollExpireNotifyValid;
};

#endif // BITCOIN_QT_OPTIONSDIALOG_H
12 changes: 12 additions & 0 deletions src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ void OptionsModel::Init()
fLimitTxnDisplay = settings.value("fLimitTxnDisplay", false).toBool();
fMaskValues = settings.value("fMaskValues", false).toBool();
limitTxnDate = settings.value("limitTxnDate", QDate()).toDate();
pollExpireNotification = settings.value("pollExpireNotification", 1.0).toDouble();
nReserveBalance = settings.value("nReserveBalance").toLongLong();
language = settings.value("language", "").toString();
walletStylesheet = settings.value("walletStylesheet", "dark").toString();
Expand Down Expand Up @@ -142,6 +143,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return QVariant(fMaskValues);
case LimitTxnDate:
return QVariant(limitTxnDate);
case PollExpireNotification:
return QVariant(pollExpireNotification);
case DisableUpdateCheck:
return QVariant(gArgs.GetBoolArg("-disableupdatecheck", false));
case DataDir:
Expand Down Expand Up @@ -284,6 +287,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
limitTxnDate = value.toDate();
settings.setValue("limitTxnDate", limitTxnDate);
break;
case PollExpireNotification:
pollExpireNotification = value.toDouble();
settings.setValue("pollExpireNotification", pollExpireNotification);
break;
case DisableUpdateCheck:
gArgs.ForceSetArg("-disableupdatecheck", value.toBool() ? "1" : "0");
settings.setValue("fDisableUpdateCheck", value.toBool());
Expand Down Expand Up @@ -380,6 +387,11 @@ int64_t OptionsModel::getLimitTxnDateTime()
return limitTxnDateTime.toMSecsSinceEpoch() / 1000;
}

double OptionsModel::getPollExpireNotification()
{
return pollExpireNotification;
}

bool OptionsModel::getStartAtStartup()
{
return fStartAtStartup;
Expand Down
5 changes: 4 additions & 1 deletion src/qt/optionsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class OptionsModel : public QAbstractListModel
EnableStakeSplit, // bool
StakingEfficiency, // double
MinStakeSplitValue, // int
PollExpireNotification, // double
ContractChangeToInput, // bool
MaskValues, // bool
OptionIDRowCount
Expand Down Expand Up @@ -71,6 +72,7 @@ class OptionsModel : public QAbstractListModel
bool getMaskValues();
QDate getLimitTxnDate();
int64_t getLimitTxnDateTime();
double getPollExpireNotification();
QString getLanguage() { return language; }
QString getCurrentStyle();
QString getDataDir();
Expand All @@ -87,13 +89,14 @@ class OptionsModel : public QAbstractListModel
bool fStartMin;
bool fDisableTrxNotifications;
bool fDisablePollNotifications;
bool bDisplayAddresses;
bool bDisplayAddresses;
bool fMinimizeOnClose;
bool fConfirmOnClose;
bool fCoinControlFeatures;
bool fLimitTxnDisplay;
bool fMaskValues;
QDate limitTxnDate;
double pollExpireNotification;
QString language;
QString walletStylesheet;
QString dataDir;
Expand Down
Loading

0 comments on commit b075021

Please sign in to comment.