neobytes/src/qt/masternodelist.cpp

394 lines
14 KiB
C++
Raw Normal View History

2016-05-11 13:09:31 +02:00
#include "masternodelist.h"
#include "ui_masternodelist.h"
#include "sync.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "activemasternode.h"
#include "masternode-sync.h"
#include "masternodeconfig.h"
#include "masternodeman.h"
#include "wallet/wallet.h"
#include "init.h"
#include "guiutil.h"
2016-05-11 13:09:31 +02:00
#include <QTimer>
#include <QMessageBox>
CCriticalSection cs_masternodes;
MasternodeList::MasternodeList(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::MasternodeList),
clientModel(0),
walletModel(0)
{
ui->setupUi(this);
ui->startButton->setEnabled(false);
int columnAliasWidth = 100;
int columnAddressWidth = 200;
int columnProtocolWidth = 60;
int columnStatusWidth = 80;
int columnActiveWidth = 130;
int columnLastSeenWidth = 130;
ui->tableWidgetMyMasternodes->setColumnWidth(0, columnAliasWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(1, columnAddressWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(2, columnProtocolWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(3, columnStatusWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(4, columnActiveWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(5, columnLastSeenWidth);
ui->tableWidgetMasternodes->setColumnWidth(0, columnAddressWidth);
ui->tableWidgetMasternodes->setColumnWidth(1, columnProtocolWidth);
ui->tableWidgetMasternodes->setColumnWidth(2, columnStatusWidth);
ui->tableWidgetMasternodes->setColumnWidth(3, columnActiveWidth);
ui->tableWidgetMasternodes->setColumnWidth(4, columnLastSeenWidth);
2016-05-11 13:09:31 +02:00
ui->tableWidgetMyMasternodes->setContextMenuPolicy(Qt::CustomContextMenu);
QAction *startAliasAction = new QAction(tr("Start alias"), this);
contextMenu = new QMenu();
contextMenu->addAction(startAliasAction);
connect(ui->tableWidgetMyMasternodes, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)));
connect(startAliasAction, SIGNAL(triggered()), this, SLOT(on_startButton_clicked()));
2016-05-11 13:09:31 +02:00
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateNodeList()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateMyNodeList()));
timer->start(1000);
updateNodeList();
}
MasternodeList::~MasternodeList()
{
delete ui;
}
void MasternodeList::setClientModel(ClientModel *model)
{
this->clientModel = model;
if(model) {
2016-05-11 13:09:31 +02:00
// try to update list when masternode count changes
2016-05-16 21:27:43 +02:00
connect(clientModel, SIGNAL(strMasternodesChanged(QString)), this, SLOT(updateNodeList()));
2016-05-11 13:09:31 +02:00
}
}
void MasternodeList::setWalletModel(WalletModel *model)
{
this->walletModel = model;
}
void MasternodeList::showContextMenu(const QPoint &point)
{
QTableWidgetItem *item = ui->tableWidgetMyMasternodes->itemAt(point);
if(item) contextMenu->exec(QCursor::pos());
}
2016-05-11 13:09:31 +02:00
void MasternodeList::StartAlias(std::string strAlias)
{
std::string strStatusHtml;
strStatusHtml += "<center>Alias: " + strAlias;
2016-05-11 13:09:31 +02:00
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
if(mne.getAlias() == strAlias) {
std::string strError;
2016-05-11 13:09:31 +02:00
CMasternodeBroadcast mnb;
bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
2016-05-11 13:09:31 +02:00
if(fSuccess) {
strStatusHtml += "<br>Successfully started masternode.";
2016-05-11 13:09:31 +02:00
mnodeman.UpdateMasternodeList(mnb);
mnb.Relay();
} else {
strStatusHtml += "<br>Failed to start masternode.<br>Error: " + strError;
2016-05-11 13:09:31 +02:00
}
break;
}
}
strStatusHtml += "</center>";
2016-05-11 13:09:31 +02:00
QMessageBox msg;
msg.setText(QString::fromStdString(strStatusHtml));
2016-05-11 13:09:31 +02:00
msg.exec();
updateMyNodeList(true);
2016-05-11 13:09:31 +02:00
}
void MasternodeList::StartAll(std::string strCommand)
{
int nCountSuccessful = 0;
int nCountFailed = 0;
std::string strFailedHtml;
2016-05-11 13:09:31 +02:00
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
std::string strError;
2016-05-11 13:09:31 +02:00
CMasternodeBroadcast mnb;
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(txin);
2016-05-11 13:09:31 +02:00
if(strCommand == "start-missing" && pmn) continue;
bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
2016-05-11 13:09:31 +02:00
if(fSuccess) {
nCountSuccessful++;
2016-05-11 13:09:31 +02:00
mnodeman.UpdateMasternodeList(mnb);
mnb.Relay();
} else {
nCountFailed++;
strFailedHtml += "\nFailed to start " + mne.getAlias() + ". Error: " + strError;
2016-05-11 13:09:31 +02:00
}
}
pwalletMain->Lock();
std::string returnObj;
returnObj = strprintf("Successfully started %d masternodes, failed to start %d, total %d", nCountSuccessful, nCountFailed, nCountFailed + nCountSuccessful);
if (nCountFailed > 0) {
returnObj += strFailedHtml;
}
2016-05-11 13:09:31 +02:00
QMessageBox msg;
msg.setText(QString::fromStdString(returnObj));
msg.exec();
updateMyNodeList(true);
2016-05-11 13:09:31 +02:00
}
void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, CMasternode *pmn)
2016-05-11 13:09:31 +02:00
{
LOCK(cs_mnlistupdate);
bool fOldRowFound = false;
int nNewRow = 0;
2016-05-11 13:09:31 +02:00
for(int i = 0; i < ui->tableWidgetMyMasternodes->rowCount(); i++) {
if(ui->tableWidgetMyMasternodes->item(i, 0)->text() == strAlias) {
fOldRowFound = true;
nNewRow = i;
2016-05-11 13:09:31 +02:00
break;
}
}
if(nNewRow == 0 && !fOldRowFound) {
nNewRow = ui->tableWidgetMyMasternodes->rowCount();
ui->tableWidgetMyMasternodes->insertRow(nNewRow);
2016-05-11 13:09:31 +02:00
}
QTableWidgetItem *aliasItem = new QTableWidgetItem(strAlias);
QTableWidgetItem *addrItem = new QTableWidgetItem(pmn ? QString::fromStdString(pmn->addr.ToString()) : strAddr);
2016-05-11 13:09:31 +02:00
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(pmn ? pmn->protocolVersion : -1));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(pmn ? pmn->Status() : "MISSING"));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(pmn ? (pmn->lastPing.sigTime - pmn->sigTime) : 0)));
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M", pmn ? pmn->lastPing.sigTime : 0)));
2016-05-11 13:09:31 +02:00
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(pmn ? CBitcoinAddress(pmn->pubkey.GetID()).ToString() : ""));
ui->tableWidgetMyMasternodes->setItem(nNewRow, 0, aliasItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 2, protocolItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 3, statusItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 4, activeSecondsItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 5, lastSeenItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 6, pubkeyItem);
2016-05-11 13:09:31 +02:00
}
void MasternodeList::updateMyNodeList(bool fForce)
{
static int64_t nTimeMyListUpdated = 0;
2016-05-11 13:09:31 +02:00
// automatically update my masternode list only once in MY_MASTERNODELIST_UPDATE_SECONDS seconds,
// this update still can be triggered manually at any time via button click
int64_t nSecondsTillUpdate = nTimeMyListUpdated + MY_MASTERNODELIST_UPDATE_SECONDS - GetTime();
ui->secondsLabel->setText(QString::number(nSecondsTillUpdate));
2016-05-11 13:09:31 +02:00
if(nSecondsTillUpdate > 0 && !fForce) return;
nTimeMyListUpdated = GetTime();
2016-05-11 13:09:31 +02:00
ui->tableWidgetMasternodes->setSortingEnabled(false);
2016-05-11 13:09:31 +02:00
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(txin);
2016-05-11 13:09:31 +02:00
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), pmn);
2016-05-11 13:09:31 +02:00
}
ui->tableWidgetMasternodes->setSortingEnabled(true);
2016-05-11 13:09:31 +02:00
// reset "timer"
ui->secondsLabel->setText("0");
}
void MasternodeList::updateNodeList()
{
static int64_t nTimeListUpdated = GetTime();
2016-05-11 13:09:31 +02:00
// to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
// or MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds after filter was last changed
int64_t nSecondsToWait = fFilterUpdated
? nTimeFilterUpdated - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS
: nTimeListUpdated - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
if(fFilterUpdated) ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
if(nSecondsToWait > 0) return;
nTimeListUpdated = GetTime();
fFilterUpdated = false;
2016-05-11 13:09:31 +02:00
TRY_LOCK(cs_masternodes, lockMasternodes);
if(!lockMasternodes) return;
2016-05-11 13:09:31 +02:00
QString strToFilter;
ui->countLabel->setText("Updating...");
ui->tableWidgetMasternodes->setSortingEnabled(false);
ui->tableWidgetMasternodes->clearContents();
ui->tableWidgetMasternodes->setRowCount(0);
2016-05-11 13:09:31 +02:00
std::vector<CMasternode> vMasternodes = mnodeman.GetFullMasternodeVector();
BOOST_FOREACH(CMasternode& mn, vMasternodes)
{
// populate list
// Address, Protocol, Status, Active Seconds, Last Seen, Pub Key
QTableWidgetItem *addressItem = new QTableWidgetItem(QString::fromStdString(mn.addr.ToString()));
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(mn.protocolVersion));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(mn.Status()));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(mn.lastPing.sigTime - mn.sigTime)));
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M", mn.lastPing.sigTime)));
2016-05-11 13:09:31 +02:00
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(CBitcoinAddress(mn.pubkey.GetID()).ToString()));
if (strCurrentFilter != "")
{
strToFilter = addressItem->text() + " " +
protocolItem->text() + " " +
statusItem->text() + " " +
activeSecondsItem->text() + " " +
lastSeenItem->text() + " " +
pubkeyItem->text();
if (!strToFilter.contains(strCurrentFilter)) continue;
}
ui->tableWidgetMasternodes->insertRow(0);
ui->tableWidgetMasternodes->setItem(0, 0, addressItem);
ui->tableWidgetMasternodes->setItem(0, 1, protocolItem);
ui->tableWidgetMasternodes->setItem(0, 2, statusItem);
ui->tableWidgetMasternodes->setItem(0, 3, activeSecondsItem);
ui->tableWidgetMasternodes->setItem(0, 4, lastSeenItem);
ui->tableWidgetMasternodes->setItem(0, 5, pubkeyItem);
2016-05-11 13:09:31 +02:00
}
ui->countLabel->setText(QString::number(ui->tableWidgetMasternodes->rowCount()));
ui->tableWidgetMasternodes->setSortingEnabled(true);
2016-05-11 13:09:31 +02:00
}
void MasternodeList::on_filterLineEdit_textChanged(const QString &strFilterIn)
{
strCurrentFilter = strFilterIn;
nTimeFilterUpdated = GetTime();
fFilterUpdated = true;
ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", MASTERNODELIST_FILTER_COOLDOWN_SECONDS)));
2016-05-11 13:09:31 +02:00
}
void MasternodeList::on_startButton_clicked()
{
// Find selected node alias
QItemSelectionModel* selectionModel = ui->tableWidgetMyMasternodes->selectionModel();
2016-05-11 13:09:31 +02:00
QModelIndexList selected = selectionModel->selectedRows();
if(selected.count() == 0) return;
2016-05-11 13:09:31 +02:00
QModelIndex index = selected.at(0);
int nSelectedRow = index.row();
std::string strAlias = ui->tableWidgetMyMasternodes->item(nSelectedRow, 0)->text().toStdString();
2016-05-11 13:09:31 +02:00
// Display message box
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm masternode start"),
tr("Are you sure you want to start masternode %1?").arg(QString::fromStdString(strAlias)),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if(retval != QMessageBox::Yes) return;
2016-05-11 13:09:31 +02:00
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());
if(!ctx.isValid()) return; // Unlock wallet was cancelled
2016-05-11 13:09:31 +02:00
StartAlias(strAlias);
return;
}
StartAlias(strAlias);
}
void MasternodeList::on_startAllButton_clicked()
{
// Display message box
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm all masternodes start"),
tr("Are you sure you want to start ALL masternodes?"),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if(retval != QMessageBox::Yes) return;
2016-05-11 13:09:31 +02:00
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());
if(!ctx.isValid()) return; // Unlock wallet was cancelled
2016-05-11 13:09:31 +02:00
StartAll();
return;
}
StartAll();
}
void MasternodeList::on_startMissingButton_clicked()
{
if(!masternodeSync.IsMasternodeListSynced()) {
2016-05-11 13:09:31 +02:00
QMessageBox::critical(this, tr("Command is not available right now"),
tr("You can't use this command until masternode list is synced"));
return;
}
// Display message box
QMessageBox::StandardButton retval = QMessageBox::question(this,
tr("Confirm missing masternodes start"),
tr("Are you sure you want to start MISSING masternodes?"),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if(retval != QMessageBox::Yes) return;
2016-05-11 13:09:31 +02:00
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForMixingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());
if(!ctx.isValid()) return; // Unlock wallet was cancelled
2016-05-11 13:09:31 +02:00
StartAll("start-missing");
return;
}
StartAll("start-missing");
}
void MasternodeList::on_tableWidgetMyMasternodes_itemSelectionChanged()
2016-05-11 13:09:31 +02:00
{
if(ui->tableWidgetMyMasternodes->selectedItems().count() > 0) {
2016-05-11 13:09:31 +02:00
ui->startButton->setEnabled(true);
}
}
void MasternodeList::on_UpdateButton_clicked()
{
updateMyNodeList(true);
}