Skip to content

Commit

Permalink
Merge pull request #2738 from jamescowens/improve_update_dialog
Browse files Browse the repository at this point in the history
gui, util: Improve upgrade dialog
  • Loading branch information
jamescowens authored Feb 21, 2024
2 parents 871aad2 + a59051a commit a6c2118
Show file tree
Hide file tree
Showing 18 changed files with 390 additions and 65 deletions.
4 changes: 4 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ QT_FORMS_UI = \
qt/forms/sendcoinsentry.ui \
qt/forms/signverifymessagedialog.ui \
qt/forms/transactiondescdialog.ui \
qt/forms/updatedialog.ui \
qt/forms/voting/additionalfieldstableview.ui \
qt/forms/voting/pollcard.ui \
qt/forms/voting/pollcardview.ui \
Expand Down Expand Up @@ -171,6 +172,7 @@ QT_MOC_CPP = \
qt/moc_transactionfilterproxy.cpp \
qt/moc_transactiontablemodel.cpp \
qt/moc_transactionview.cpp \
qt/moc_updatedialog.cpp \
qt/moc_walletmodel.cpp \
qt/researcher/moc_projecttablemodel.cpp \
qt/researcher/moc_researchermodel.cpp \
Expand Down Expand Up @@ -298,6 +300,7 @@ GRIDCOINRESEARCH_QT_H = \
qt/transactionrecord.h \
qt/transactiontablemodel.h \
qt/transactionview.h \
qt/updatedialog.h \
qt/upgradeqt.h \
qt/voting/additionalfieldstableview.h \
qt/voting/additionalfieldstablemodel.h \
Expand Down Expand Up @@ -388,6 +391,7 @@ GRIDCOINRESEARCH_QT_CPP = \
qt/transactiontablemodel.cpp \
qt/transactionview.cpp \
qt/upgradeqt.cpp \
qt/updatedialog.cpp \
qt/voting/additionalfieldstableview.cpp \
qt/voting/additionalfieldstablemodel.cpp \
qt/voting/poll_types.cpp \
Expand Down
115 changes: 73 additions & 42 deletions src/gridcoin/upgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ Upgrade::Upgrade()

void Upgrade::ScheduledUpdateCheck()
{
std::string VersionResponse = "";
std::string VersionResponse;
std::string change_log;

Upgrade::UpgradeType upgrade_type {Upgrade::UpgradeType::Unknown};

CheckForLatestUpdate(VersionResponse);
CheckForLatestUpdate(VersionResponse, change_log, upgrade_type);
}

bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dialog, bool snapshotrequest)
bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, std::string& change_log, Upgrade::UpgradeType& upgrade_type,
bool ui_dialog, bool snapshotrequest)
{
// If testnet skip this || If the user changes this to disable while wallet running just drop out of here now.
// (Need a way to remove items from scheduler.)
Expand All @@ -46,8 +50,8 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial

Http VersionPull;

std::string GithubResponse = "";
std::string VersionResponse = "";
std::string GithubResponse;
std::string VersionResponse;

// We receive the response and it's in a json reply
UniValue Response(UniValue::VOBJ);
Expand All @@ -64,15 +68,15 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial

if (VersionResponse.empty())
{
LogPrintf("WARNING %s: No Response from GitHub", __func__);
LogPrintf("WARNING: %s: No Response from GitHub", __func__);

return false;
}

std::string GithubReleaseData = "";
std::string GithubReleaseTypeData = "";
std::string GithubReleaseBody = "";
std::string GithubReleaseType = "";
std::string GithubReleaseData;
std::string GithubReleaseTypeData;
std::string GithubReleaseBody;
std::string GithubReleaseType;

try
{
Expand All @@ -95,14 +99,19 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial
}

GithubReleaseTypeData = ToLower(GithubReleaseTypeData);
if (GithubReleaseTypeData.find("leisure") != std::string::npos)
GithubReleaseType = _("leisure");

else if (GithubReleaseTypeData.find("mandatory") != std::string::npos)
if (GithubReleaseTypeData.find("leisure") != std::string::npos) {
GithubReleaseType = _("leisure");
upgrade_type = Upgrade::UpgradeType::Leisure;
} else if (GithubReleaseTypeData.find("mandatory") != std::string::npos) {
GithubReleaseType = _("mandatory");

else
// This will be confirmed below by also checking the second position version. If not incremented, then it will
// be set to unknown.
upgrade_type = Upgrade::UpgradeType::Mandatory;
} else {
GithubReleaseType = _("unknown");
upgrade_type = Upgrade::UpgradeType::Unknown;
}

// Parse version data
std::vector<std::string> GithubVersion;
Expand All @@ -113,6 +122,7 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial
LocalVersion.push_back(CLIENT_VERSION_MAJOR);
LocalVersion.push_back(CLIENT_VERSION_MINOR);
LocalVersion.push_back(CLIENT_VERSION_REVISION);
LocalVersion.push_back(CLIENT_VERSION_BUILD);

if (GithubVersion.size() != 4)
{
Expand All @@ -123,60 +133,79 @@ bool Upgrade::CheckForLatestUpdate(std::string& client_message_out, bool ui_dial

bool NewVersion = false;
bool NewMandatory = false;
bool same_version = true;

try {
// Left to right version numbers.
// 3 numbers to check for production.
for (unsigned int x = 0; x < 3; x++)
{
// 4 numbers to check.
for (unsigned int x = 0; x <= 3; x++) {
int github_version = 0;

if (!ParseInt32(GithubVersion[x], &github_version))
{
if (!ParseInt32(GithubVersion[x], &github_version)) {
throw std::invalid_argument("Failed to parse GitHub version from official GitHub project repo.");
}

if (github_version > LocalVersion[x])
{
if (github_version > LocalVersion[x]) {
NewVersion = true;
if (x < 2)
{
same_version = false;

if (x < 2 && upgrade_type == Upgrade::UpgradeType::Mandatory) {
NewMandatory = true;
} else {
upgrade_type = Upgrade::UpgradeType::Unknown;
}
break;
} else {
same_version &= (github_version == LocalVersion[x]);
}
}
}
catch (std::exception& ex)
{
} catch (std::exception& ex) {
error("%s: Exception occurred checking client version against GitHub version (%s)",
__func__, ToString(ex.what()));

upgrade_type = Upgrade::UpgradeType::Unknown;
return false;
}

if (!NewVersion) return NewVersion;

// New version was found
// Populate client_message_out regardless of whether new version is found, because we are using this method for
// the version information button in the "About Gridcoin" dialog.
client_message_out = _("Local version: ") + strprintf("%d.%d.%d.%d", CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR,
CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) + "\r\n";
client_message_out.append(_("GitHub version: ") + GithubReleaseData + "\r\n");
client_message_out.append(_("This update is ") + GithubReleaseType + "\r\n\r\n");

// For snapshot requests we will handle things differently after this point
if (snapshotrequest && NewMandatory)
return NewVersion;
if (NewVersion) {
client_message_out.append(_("This update is ") + GithubReleaseType + "\r\n\r\n");
} else if (same_version) {
client_message_out.append(_("The latest release is ") + GithubReleaseType + "\r\n\r\n");
client_message_out.append(_("You are running the latest release.") + "\n");
} else {
client_message_out.append(_("The latest release is ") + GithubReleaseType + "\r\n\r\n");

// If not a new version available and the version is not the same, the only thing left is that we are running
// a version greater than the latest release version, so set the upgrade_type to Unsupported, which is used for a
// warning.
upgrade_type = Upgrade::UpgradeType::Unsupported;
client_message_out.append(_("WARNING: You are running a version that is higher than the latest release.") + "\n");
}

change_log = GithubReleaseBody;

if (!NewVersion) return false;

if (NewMandatory)
// For snapshot requests we will only return true if there is a new mandatory version AND the snapshotrequest boolean
// is set true. This is because the snapshot request context is looking for the presence of a new mandatory to block
// the snapshot download before upgrading to the new mandatory if there is one.
if (snapshotrequest && NewMandatory) return true;

if (NewMandatory) {
client_message_out.append(_("WARNING: A mandatory release is available. Please upgrade as soon as possible.")
+ "\n");
}

std::string ChangeLog = GithubReleaseBody;

if (ui_dialog)
uiInterface.UpdateMessageBox(client_message_out, ChangeLog);
if (ui_dialog) {
uiInterface.UpdateMessageBox(client_message_out, static_cast<int>(upgrade_type), change_log);
}

return NewVersion;
return true;
}

void Upgrade::SnapshotMain()
Expand All @@ -188,8 +217,10 @@ void Upgrade::SnapshotMain()

// Verify a mandatory release is not available before we continue to snapshot download.
std::string VersionResponse = "";
std::string change_log;
Upgrade::UpgradeType upgrade_type {Upgrade::UpgradeType::Unknown};

if (CheckForLatestUpdate(VersionResponse, false, true))
if (CheckForLatestUpdate(VersionResponse, change_log, upgrade_type, false, true))
{
std::cout << this->ResetBlockchainMessages(UpdateAvailable) << std::endl;
std::cout << this->ResetBlockchainMessages(GithubResponse) << std::endl;
Expand Down
10 changes: 9 additions & 1 deletion src/gridcoin/upgrade.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ class Upgrade
GithubResponse
};

enum UpgradeType {
Unknown,
Leisure,
Mandatory,
Unsupported //! This is used for a running version that is greater than the current official release.
};

//!
//! \brief Scheduler call to CheckForLatestUpdate
//!
Expand All @@ -133,7 +140,8 @@ class Upgrade
//!
//! \brief Check for latest updates on GitHub.
//!
static bool CheckForLatestUpdate(std::string& client_message_out, bool ui_dialog = true, bool snapshotrequest = false);
static bool CheckForLatestUpdate(std::string& client_message_out, std::string& change_log, UpgradeType& upgrade_type,
bool ui_dialog = true, bool snapshotrequest = false);

//!
//! \brief Function that will be threaded to download snapshot
Expand Down
2 changes: 1 addition & 1 deletion src/node/ui_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ ADD_SIGNALS_IMPL_WRAPPER(UpdateMessageBox);
ADD_SIGNALS_IMPL_WRAPPER(RwSettingsUpdated);

void CClientUIInterface::ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style); }
void CClientUIInterface::UpdateMessageBox(const std::string& version, const std::string& message) { return g_ui_signals.UpdateMessageBox(version, message); }
void CClientUIInterface::UpdateMessageBox(const std::string& version, const int& update_type, const std::string& message) { return g_ui_signals.UpdateMessageBox(version, update_type, message); }
bool CClientUIInterface::ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) { return g_ui_signals.ThreadSafeAskFee(nFeeRequired, strCaption).value_or(false); }
bool CClientUIInterface::ThreadSafeAskQuestion(std::string caption, std::string body) { return g_ui_signals.ThreadSafeAskQuestion(caption, body).value_or(false); }
void CClientUIInterface::ThreadSafeHandleURI(const std::string& strURI) { return g_ui_signals.ThreadSafeHandleURI(strURI); }
Expand Down
2 changes: 1 addition & 1 deletion src/node/ui_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class CClientUIInterface
ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, void, const std::string& message, const std::string& caption, int style);

/** Update notification message box. */
ADD_SIGNALS_DECL_WRAPPER(UpdateMessageBox, void, const std::string& version, const std::string& message);
ADD_SIGNALS_DECL_WRAPPER(UpdateMessageBox, void, const std::string& version, const int& update_type, const std::string& message);

/** Ask the user whether they want to pay a fee or not. */
ADD_SIGNALS_DECL_WRAPPER(ThreadSafeAskFee, bool, int64_t nFeeRequired, const std::string& strCaption);
Expand Down
2 changes: 1 addition & 1 deletion src/noui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ static bool noui_ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCa
return true;
}

static int noui_UpdateMessageBox(const std::string& version, const std::string& message)
static int noui_UpdateMessageBox(const std::string& version, const int& upgrade_type, const std::string& message)
{
std::string caption = _("Gridcoin Update Available");

Expand Down
1 change: 1 addition & 0 deletions src/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ add_library(gridcoinqt STATIC
transactionrecord.cpp
transactiontablemodel.cpp
transactionview.cpp
updatedialog.cpp
upgradeqt.cpp
voting/additionalfieldstableview.cpp
voting/additionalfieldstablemodel.cpp
Expand Down
56 changes: 55 additions & 1 deletion src/qt/aboutdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,44 @@
#include "qt/decoration.h"
#include "ui_aboutdialog.h"
#include "clientmodel.h"
#include "updatedialog.h"
#include "util.h"

AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AboutDialog)
{
ui->setupUi(this);
ui->copyrightLabel->setText("Copyright 2009-2024 The Bitcoin/Peercoin/Black-Coin/Gridcoin developers");

QString copyrightText = "Copyright 2009-";
std::variant<int, QString> copyright_year = COPYRIGHT_YEAR;

try {
copyrightText += QString::number(std::get<int>(copyright_year));
} catch (const std::bad_variant_access& e) {
try {
copyrightText += std::get<QString>(copyright_year);
} catch (const std::bad_variant_access& e) {
copyrightText += "Present";
}
}

copyrightText += " The Bitcoin/Peercoin/Black-Coin/Gridcoin developers";

ui->copyrightLabel->setText(copyrightText);

resize(GRC::ScaleSize(this, width(), height()));

if (!fTestNet && !gArgs.GetBoolArg("-disableupdatecheck", false)) {
connect(ui->versionInfoButton, &QAbstractButton::pressed, this, [this]() { handlePressVersionInfoButton(); });
} else if (gArgs.GetBoolArg("-disableupdatecheck", false)) {
ui->versionInfoButton->setDisabled(true);
ui->versionInfoButton->setToolTip(tr("Version information and update check has been disabled "
"by config or startup parameter."));
} else {
ui->versionInfoButton->setDisabled(true);
ui->versionInfoButton->setToolTip(tr("Version information is not available on testnet."));
}
}

void AboutDialog::setModel(ClientModel *model)
Expand All @@ -30,3 +59,28 @@ void AboutDialog::on_buttonBox_accepted()
{
close();
}

void AboutDialog::handlePressVersionInfoButton()
{
std::string client_message_out;
std::string change_log;
GRC::Upgrade::UpgradeType upgrade_type = GRC::Upgrade::UpgradeType::Unknown;


GRC::Upgrade::CheckForLatestUpdate(client_message_out, change_log, upgrade_type, false, false);

if (client_message_out == std::string {}) {
client_message_out = "No response from GitHub - check network connectivity.";
change_log = " ";
}

UpdateDialog update_dialog;

update_dialog.setWindowTitle("Gridcoin Version Information");
update_dialog.setVersion(QString().fromStdString(client_message_out));
update_dialog.setUpgradeType(static_cast<GRC::Upgrade::UpgradeType>(upgrade_type));
update_dialog.setDetails(QString().fromStdString(change_log));
update_dialog.setModal(false);

update_dialog.exec();
}
1 change: 1 addition & 0 deletions src/qt/aboutdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class AboutDialog : public QDialog

private slots:
void on_buttonBox_accepted();
void handlePressVersionInfoButton();
};

#endif // BITCOIN_QT_ABOUTDIALOG_H
6 changes: 3 additions & 3 deletions src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,16 @@ static void InitMessage(const std::string &message)
}
}

static void UpdateMessageBox(const std::string& version, const std::string& message)
static void UpdateMessageBox(const std::string& version, const int& update_version, const std::string& message)
{
std::string caption = _("Gridcoin Update Available");

if (guiref)
{
std::string guiaddition = version + _("Click \"Show Details\" to view changes in latest update.");
QMetaObject::invokeMethod(guiref, "update", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(caption)),
Q_ARG(QString, QString::fromStdString(guiaddition)),
Q_ARG(QString, QString::fromStdString(version)),
Q_ARG(int, update_version),
Q_ARG(QString, QString::fromStdString(message)));
}

Expand Down
Loading

0 comments on commit a6c2118

Please sign in to comment.