diff --git a/src/qt/dogecash/forms/masternodeswidget.ui b/src/qt/dogecash/forms/masternodeswidget.ui
index 168c58441b..87b6fd357a 100644
--- a/src/qt/dogecash/forms/masternodeswidget.ui
+++ b/src/qt/dogecash/forms/masternodeswidget.ui
@@ -283,6 +283,32 @@
+ -
+
+
+
+ 125
+ 50
+
+
+
+ Start All
+
+
+
+ -
+
+
+
+ 125
+ 50
+
+
+
+ Start Missing
+
+
+
-
diff --git a/src/qt/dogecash/masternodeswidget.cpp b/src/qt/dogecash/masternodeswidget.cpp
index 53ecd4c282..259a1ac591 100644
--- a/src/qt/dogecash/masternodeswidget.cpp
+++ b/src/qt/dogecash/masternodeswidget.cpp
@@ -29,6 +29,8 @@
#define DECORATION_SIZE 65
#define NUM_ITEMS 3
+#define REQUEST_START_ALL 1
+#define REQUEST_START_MISSING 2
class MNHolder : public FurListRow
{
@@ -65,7 +67,8 @@ class MNHolder : public FurListRow
MasterNodesWidget::MasterNodesWidget(DogeCashGUI *parent) :
PWidget(parent),
- ui(new Ui::MasterNodesWidget)
+ ui(new Ui::MasterNodesWidget),
+ isLoading(false)
{
ui->setupUi(this);
@@ -99,6 +102,8 @@ MasterNodesWidget::MasterNodesWidget(DogeCashGUI *parent) :
/* Buttons */
ui->pushButtonSave->setText(tr("Create Masternode Controller"));
setCssBtnPrimary(ui->pushButtonSave);
+ setCssBtnPrimary(ui->pushButtonStartAll);
+ setCssBtnPrimary(ui->pushButtonStartMissing);
/* Options */
ui->btnAbout->setTitleClassAndText("btn-title-grey", "What is a Masternode?");
@@ -119,6 +124,12 @@ MasterNodesWidget::MasterNodesWidget(DogeCashGUI *parent) :
setCssProperty(ui->labelEmpty, "text-empty");
connect(ui->pushButtonSave, SIGNAL(clicked()), this, SLOT(onCreateMNClicked()));
+ connect(ui->pushButtonStartAll, &QPushButton::clicked, [this]() {
+ onStartAllClicked(REQUEST_START_ALL);
+ });
+ connect(ui->pushButtonStartMissing, &QPushButton::clicked, [this]() {
+ onStartAllClicked(REQUEST_START_MISSING);
+ });
connect(ui->listMn, SIGNAL(clicked(QModelIndex)), this, SLOT(onMNClicked(QModelIndex)));
connect(ui->btnAbout, &OptionButton::clicked, [this](){window->openFAQ(9);});
connect(ui->btnAboutController, &OptionButton::clicked, [this](){window->openFAQ(10);});
@@ -146,13 +157,10 @@ void MasterNodesWidget::loadWalletModel(){
}
void MasterNodesWidget::updateListState() {
- if (mnModel->rowCount() > 0) {
- ui->listMn->setVisible(true);
- ui->emptyContainer->setVisible(false);
- } else {
- ui->listMn->setVisible(false);
- ui->emptyContainer->setVisible(true);
- }
+ bool show = mnModel->rowCount() > 0;
+ ui->listMn->setVisible(show);
+ ui->emptyContainer->setVisible(!show);
+ ui->pushButtonStartAll->setVisible(show);
}
void MasterNodesWidget::onMNClicked(const QModelIndex &index){
@@ -206,19 +214,81 @@ void MasterNodesWidget::startAlias(QString strAlias){
for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) {
if (mne.getAlias() == strAlias.toStdString()) {
std::string strError;
- CMasternodeBroadcast mnb;
- if (CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb)) {
- strStatusHtml += "successfully started.";
- mnodeman.UpdateMasternodeList(mnb);
- mnb.Relay();
- mnModel->updateMNList();
- } else {
- strStatusHtml += "failed to start.\nError: " + QString::fromStdString(strError);
- }
+ strStatusHtml += (!startMN(mne, strError)) ? ("failed to start.\nError: " + QString::fromStdString(strError)) : "successfully started.";
break;
}
}
- inform(strStatusHtml);
+ // update UI and notify
+ updateModelAndInform(strStatusHtml);
+}
+
+void MasterNodesWidget::updateModelAndInform(QString informText) {
+ mnModel->updateMNList();
+ inform(informText);
+}
+
+bool MasterNodesWidget::startMN(CMasternodeConfig::CMasternodeEntry mne, std::string& strError) {
+ CMasternodeBroadcast mnb;
+ if (!CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb))
+ return false;
+
+ mnodeman.UpdateMasternodeList(mnb);
+ mnb.Relay();
+ return true;
+}
+
+void MasterNodesWidget::onStartAllClicked(int type) {
+ if(!verifyWalletUnlocked()) return;
+ if (isLoading) {
+ inform(tr("Background task is being executed, please wait"));
+ } else {
+ isLoading = true;
+ if (!execute(type)) {
+ isLoading = false;
+ inform(tr("Cannot perform Mastenodes start"));
+ }
+ }
+}
+
+bool MasterNodesWidget::startAll(QString& failText, bool onlyMissing) {
+ int amountOfMnFailed = 0;
+ int amountOfMnStarted = 0;
+ for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) {
+ // Check for only missing
+ if (onlyMissing && !mnModel->isMNMissingOrExpired(QString::fromStdString(mne.getAlias())))
+ continue;
+
+ std::string strError;
+ if (!startMN(mne, strError)) {
+ amountOfMnFailed++;
+ } else {
+ amountOfMnStarted++;
+ }
+ }
+ if (amountOfMnFailed > 0) {
+ failText = tr("%1 Masternodes failed to start, %2 started").arg(amountOfMnFailed).arg(amountOfMnStarted);
+ return false;
+ }
+ return true;
+}
+
+void MasterNodesWidget::run(int type) {
+ bool isStartMissing = type == REQUEST_START_MISSING;
+ if (type == REQUEST_START_ALL || isStartMissing) {
+ QString failText;
+ QString inform = startAll(failText, isStartMissing) ? tr("All Masternodes started!") : failText;
+ QMetaObject::invokeMethod(this, "updateModelAndInform", Qt::QueuedConnection,
+ Q_ARG(QString, inform));
+ }
+
+ isLoading = false;
+}
+
+void MasterNodesWidget::onError(QString error, int type) {
+ if (type == REQUEST_START_ALL) {
+ QMetaObject::invokeMethod(this, "inform", Qt::QueuedConnection,
+ Q_ARG(QString, "Error starting all Masternodes"));
+ }
}
void MasterNodesWidget::onInfoMNClicked(){
diff --git a/src/qt/dogecash/masternodeswidget.h b/src/qt/dogecash/masternodeswidget.h
index 6beb7b0e5c..d90b9e11f6 100644
--- a/src/qt/dogecash/masternodeswidget.h
+++ b/src/qt/dogecash/masternodeswidget.h
@@ -13,6 +13,7 @@
#include "qt/dogecash/mnrow.h"
#include "qt/dogecash/tooltipmenu.h"
#include
+#include
class DogeCashGUI;
@@ -34,17 +35,21 @@ class MasterNodesWidget : public PWidget
~MasterNodesWidget();
void loadWalletModel() override;
+ void run(int type) override;
+ void onError(QString error, int type) override;
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private slots:
void onCreateMNClicked();
void changeTheme(bool isLightTheme, QString &theme) override;
+ void onStartAllClicked(int type);
void onMNClicked(const QModelIndex &index);
void onEditMNClicked();
void onDeleteMNClicked();
void onInfoMNClicked();
void updateListState();
+ void updateModelAndInform(QString informText);
private:
Ui::MasterNodesWidget *ui;
@@ -53,8 +58,11 @@ private slots:
TooltipMenu* menu = nullptr;
QModelIndex index;
QTimer *timer = nullptr;
+ std::atomic isLoading;
void startAlias(QString strAlias);
+ bool startAll(QString& failedMN, bool onlyMissing);
+ bool startMN(CMasternodeConfig::CMasternodeEntry mne, std::string& strError);
};
#endif // MASTERNODESWIDGET_H
diff --git a/src/qt/dogecash/mnmodel.cpp b/src/qt/dogecash/mnmodel.cpp
index ff3acb7f2a..a8f4609abd 100644
--- a/src/qt/dogecash/mnmodel.cpp
+++ b/src/qt/dogecash/mnmodel.cpp
@@ -150,4 +150,13 @@ bool MNModel::addMn(CMasternodeConfig::CMasternodeEntry* mne){
nodes.insert(QString::fromStdString(mne->getAlias()), std::make_pair(QString::fromStdString(mne->getIp()), pmn));
endInsertRows();
return true;
+}
+
+bool MNModel::isMNMissingOrExpired(QString mnAlias) {
+ QMap>::const_iterator it = nodes.find(mnAlias);
+ if (it != nodes.end()) {
+ int activeState = it.value().second->activeState;
+ return activeState == CMasternode::MASTERNODE_MISSING || activeState == CMasternode::MASTERNODE_EXPIRED;
+ }
+ throw std::runtime_error(std::string("Masternode alias not found"));
}
\ No newline at end of file
diff --git a/src/qt/dogecash/mnmodel.h b/src/qt/dogecash/mnmodel.h
index 87d8d06062..c5fc898b3d 100644
--- a/src/qt/dogecash/mnmodel.h
+++ b/src/qt/dogecash/mnmodel.h
@@ -42,10 +42,12 @@ class MNModel : public QAbstractTableModel
bool addMn(CMasternodeConfig::CMasternodeEntry* entry);
void updateMNList();
+ // Checks if the masternode is in missing state
+ bool isMNMissingOrExpired(QString mnAlias);
private:
// alias mn node ---> pair
- QMap> nodes;
+ QMap> nodes;
QMap collateralTxAccepted;
};