Add masternode tab in qt wallet
This commit is contained in:
parent
25c4341311
commit
3764e6869a
@ -28,6 +28,7 @@ QT_FORMS_UI = \
|
||||
qt/forms/editaddressdialog.ui \
|
||||
qt/forms/helpmessagedialog.ui \
|
||||
qt/forms/intro.ui \
|
||||
qt/forms/masternodelist.ui \
|
||||
qt/forms/openuridialog.ui \
|
||||
qt/forms/optionsdialog.ui \
|
||||
qt/forms/overviewpage.ui \
|
||||
@ -58,6 +59,7 @@ QT_MOC_CPP = \
|
||||
qt/moc_intro.cpp \
|
||||
qt/moc_macdockiconhandler.cpp \
|
||||
qt/moc_macnotificationhandler.cpp \
|
||||
qt/moc_masternodelist.cpp \
|
||||
qt/moc_notificator.cpp \
|
||||
qt/moc_openuridialog.cpp \
|
||||
qt/moc_optionsdialog.cpp \
|
||||
@ -126,6 +128,7 @@ BITCOIN_QT_H = \
|
||||
qt/intro.h \
|
||||
qt/macdockiconhandler.h \
|
||||
qt/macnotificationhandler.h \
|
||||
qt/masternodelist.h \
|
||||
qt/networkstyle.h \
|
||||
qt/notificator.h \
|
||||
qt/openuridialog.h \
|
||||
@ -388,6 +391,7 @@ BITCOIN_QT_CPP += \
|
||||
qt/coincontroltreewidget.cpp \
|
||||
qt/darksendconfig.cpp \
|
||||
qt/editaddressdialog.cpp \
|
||||
qt/masternodelist.cpp \
|
||||
qt/openuridialog.cpp \
|
||||
qt/overviewpage.cpp \
|
||||
qt/paymentrequestplus.cpp \
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "masternode-sync.h"
|
||||
#include "masternodeconfig.h"
|
||||
#include "masternodelist.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -87,6 +89,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
appMenuBar(0),
|
||||
overviewAction(0),
|
||||
historyAction(0),
|
||||
masternodeAction(0),
|
||||
quitAction(0),
|
||||
sendCoinsAction(0),
|
||||
sendCoinsMenuAction(0),
|
||||
@ -321,6 +324,19 @@ void BitcoinGUI::createActions()
|
||||
#endif
|
||||
tabGroup->addAction(historyAction);
|
||||
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Masternodes"), this);
|
||||
masternodeAction->setStatusTip(tr("Browse masternodes"));
|
||||
masternodeAction->setToolTip(masternodeAction->statusTip());
|
||||
masternodeAction->setCheckable(true);
|
||||
#ifdef Q_OS_MAC
|
||||
masternodeAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_5));
|
||||
#else
|
||||
masternodeAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
|
||||
#endif
|
||||
tabGroup->addAction(masternodeAction);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
|
||||
// can be triggered from the tray menu, and need to show the GUI to be useful.
|
||||
@ -336,6 +352,10 @@ void BitcoinGUI::createActions()
|
||||
connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
|
||||
connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
|
||||
if (masternodeConfig.getCount()) {
|
||||
connect(masternodeAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(masternodeAction, SIGNAL(triggered()), this, SLOT(gotoMasternodePage()));
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
quitAction = new QAction(QIcon(":/icons/" + theme + "/quit"), tr("E&xit"), this);
|
||||
@ -513,6 +533,10 @@ void BitcoinGUI::createToolBars()
|
||||
toolbar->addAction(sendCoinsAction);
|
||||
toolbar->addAction(receiveCoinsAction);
|
||||
toolbar->addAction(historyAction);
|
||||
if (masternodeConfig.getCount())
|
||||
{
|
||||
toolbar->addAction(masternodeAction);
|
||||
}
|
||||
toolbar->setMovable(false); // remove unused icon in upper left corner
|
||||
overviewAction->setChecked(true);
|
||||
|
||||
@ -606,6 +630,9 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
|
||||
receiveCoinsAction->setEnabled(enabled);
|
||||
receiveCoinsMenuAction->setEnabled(enabled);
|
||||
historyAction->setEnabled(enabled);
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeAction->setEnabled(enabled);
|
||||
}
|
||||
encryptWalletAction->setEnabled(enabled);
|
||||
backupWalletAction->setEnabled(enabled);
|
||||
changePassphraseAction->setEnabled(enabled);
|
||||
@ -783,6 +810,14 @@ void BitcoinGUI::gotoHistoryPage()
|
||||
if (walletFrame) walletFrame->gotoHistoryPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoMasternodePage()
|
||||
{
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeAction->setChecked(true);
|
||||
if (walletFrame) walletFrame->gotoMasternodePage();
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoReceiveCoinsPage()
|
||||
{
|
||||
receiveCoinsAction->setChecked(true);
|
||||
|
@ -30,6 +30,7 @@ class UnitDisplayStatusBarControl;
|
||||
class WalletFrame;
|
||||
class WalletModel;
|
||||
class HelpMessageDialog;
|
||||
class MasternodeList;
|
||||
|
||||
class CWallet;
|
||||
|
||||
@ -92,6 +93,7 @@ private:
|
||||
QMenuBar *appMenuBar;
|
||||
QAction *overviewAction;
|
||||
QAction *historyAction;
|
||||
QAction *masternodeAction;
|
||||
QAction *quitAction;
|
||||
QAction *sendCoinsAction;
|
||||
QAction *sendCoinsMenuAction;
|
||||
@ -196,6 +198,8 @@ private Q_SLOTS:
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to masternode page */
|
||||
void gotoMasternodePage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
|
317
src/qt/forms/masternodelist.ui
Normal file
317
src/qt/forms/masternodelist.ui
Normal file
@ -0,0 +1,317 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MasternodeList</class>
|
||||
<widget class="QWidget" name="MasternodeList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>723</width>
|
||||
<height>457</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="topLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer0">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabMyMasternodes">
|
||||
<attribute name="title">
|
||||
<string>My masternodes</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_note">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="updateNote">
|
||||
<property name="text">
|
||||
<string>Note: Status of your masternodes in local wallet can potentially be slightly incorrect.<br />Always wait for wallet to sync additional data and then double check from another node<br />if your node should be running but you still see "MISSING" in "Status" field.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>695</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Alias</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>IP/Onion</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Active (secs)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Last Seen (UTC)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Pubkey</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="text">
|
||||
<string>S&tart alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startAllButton">
|
||||
<property name="text">
|
||||
<string>Start &all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startMissingButton">
|
||||
<property name="text">
|
||||
<string>Start &MISSING</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="UpdateButton">
|
||||
<property name="text">
|
||||
<string>&Update status</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="autoupdate_label">
|
||||
<property name="text">
|
||||
<string>Status will be updated automatically in (sec):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="secondsLabel">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabAllMasternodes">
|
||||
<attribute name="title">
|
||||
<string>All masternodes</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Active (secs)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Last Seen (UTC)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Pubkey</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_filter">
|
||||
<property name="text">
|
||||
<string>Filter List:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filterLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Filter masternode list</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_count">
|
||||
<property name="text">
|
||||
<string>Node Count:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="countLabel">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
370
src/qt/masternodelist.cpp
Normal file
370
src/qt/masternodelist.cpp
Normal file
@ -0,0 +1,370 @@
|
||||
#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 <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);
|
||||
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->tableWidget_2->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
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)
|
||||
{
|
||||
// try to update list when masternode count changes
|
||||
connect(clientModel, SIGNAL(strMasternodesChanged()), this, SLOT(updateNodeList()));
|
||||
}
|
||||
}
|
||||
|
||||
void MasternodeList::setWalletModel(WalletModel *model)
|
||||
{
|
||||
this->walletModel = model;
|
||||
}
|
||||
|
||||
void MasternodeList::StartAlias(std::string strAlias) {
|
||||
|
||||
std::string statusObj;
|
||||
statusObj += "<center>Alias: " + strAlias;
|
||||
|
||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||
if(mne.getAlias() == strAlias) {
|
||||
std::string errorMessage;
|
||||
CMasternodeBroadcast mnb;
|
||||
|
||||
bool result = activeMasternode.CreateBroadcast(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage, mnb);
|
||||
|
||||
if(result) {
|
||||
statusObj += "<br>Successfully started masternode." ;
|
||||
mnodeman.UpdateMasternodeList(mnb);
|
||||
mnb.Relay();
|
||||
} else {
|
||||
statusObj += "<br>Failed to start masternode.<br>Error: " + errorMessage;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
statusObj += "</center>";
|
||||
|
||||
QMessageBox msg;
|
||||
msg.setText(QString::fromStdString(statusObj));
|
||||
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void MasternodeList::StartAll(std::string strCommand) {
|
||||
|
||||
int total = 0;
|
||||
int successful = 0;
|
||||
int fail = 0;
|
||||
std::string statusObj;
|
||||
|
||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||
std::string errorMessage;
|
||||
CMasternodeBroadcast mnb;
|
||||
|
||||
CTxIn vin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
|
||||
CMasternode *pmn = mnodeman.Find(vin);
|
||||
|
||||
if(strCommand == "start-missing" && pmn) continue;
|
||||
|
||||
bool result = activeMasternode.CreateBroadcast(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage, mnb);
|
||||
|
||||
if(result) {
|
||||
successful++;
|
||||
mnodeman.UpdateMasternodeList(mnb);
|
||||
mnb.Relay();
|
||||
} else {
|
||||
fail++;
|
||||
statusObj += "\nFailed to start " + mne.getAlias() + ". Error: " + errorMessage;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
pwalletMain->Lock();
|
||||
|
||||
std::string returnObj;
|
||||
returnObj = strprintf("Successfully started %d masternodes, failed to start %d, total %d", successful, fail, total);
|
||||
if (fail > 0)
|
||||
returnObj += statusObj;
|
||||
|
||||
QMessageBox msg;
|
||||
msg.setText(QString::fromStdString(returnObj));
|
||||
msg.exec();
|
||||
}
|
||||
|
||||
void MasternodeList::updateMyMasternodeInfo(QString alias, QString addr, QString privkey, QString txHash, QString txIndex, CMasternode *pmn)
|
||||
{
|
||||
LOCK(cs_mnlistupdate);
|
||||
bool bFound = false;
|
||||
int nodeRow = 0;
|
||||
|
||||
for(int i=0; i < ui->tableWidget_2->rowCount(); i++)
|
||||
{
|
||||
if(ui->tableWidget_2->item(i, 0)->text() == alias)
|
||||
{
|
||||
bFound = true;
|
||||
nodeRow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nodeRow == 0 && !bFound) {
|
||||
nodeRow = ui->tableWidget_2->rowCount();
|
||||
ui->tableWidget_2->insertRow(nodeRow);
|
||||
}
|
||||
|
||||
QTableWidgetItem *aliasItem = new QTableWidgetItem(alias);
|
||||
QTableWidgetItem *addrItem = new QTableWidgetItem(addr);
|
||||
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:%S", pmn ? pmn->lastPing.sigTime : 0)));
|
||||
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(pmn ? CBitcoinAddress(pmn->pubkey.GetID()).ToString() : ""));
|
||||
|
||||
ui->tableWidget_2->setItem(nodeRow, 0, aliasItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 1, addrItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 2, protocolItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 3, statusItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 4, activeSecondsItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 5, lastSeenItem);
|
||||
ui->tableWidget_2->setItem(nodeRow, 6, pubkeyItem);
|
||||
}
|
||||
|
||||
void MasternodeList::updateMyNodeList(bool reset) {
|
||||
static int64_t lastMyListUpdate = 0;
|
||||
|
||||
// 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 timeTillUpdate = lastMyListUpdate + MY_MASTERNODELIST_UPDATE_SECONDS - GetTime();
|
||||
ui->secondsLabel->setText(QString::number(timeTillUpdate));
|
||||
|
||||
if(timeTillUpdate > 0 && !reset) return;
|
||||
lastMyListUpdate = GetTime();
|
||||
|
||||
ui->tableWidget->setSortingEnabled(false);
|
||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||
CTxIn vin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
|
||||
CMasternode *pmn = mnodeman.Find(vin);
|
||||
|
||||
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), QString::fromStdString(mne.getPrivKey()), QString::fromStdString(mne.getTxHash()),
|
||||
QString::fromStdString(mne.getOutputIndex()), pmn);
|
||||
}
|
||||
ui->tableWidget->setSortingEnabled(true);
|
||||
|
||||
// reset "timer"
|
||||
ui->secondsLabel->setText("0");
|
||||
}
|
||||
|
||||
void MasternodeList::updateNodeList()
|
||||
{
|
||||
static int64_t lastListUpdate = 0;
|
||||
|
||||
// update only once in MASTERNODELIST_UPDATE_SECONDS seconds to prevent high cpu usage e.g. on filter change
|
||||
if(GetTime() - lastListUpdate < MASTERNODELIST_UPDATE_SECONDS) return;
|
||||
lastListUpdate = GetTime();
|
||||
|
||||
TRY_LOCK(cs_masternodes, lockMasternodes);
|
||||
if(!lockMasternodes)
|
||||
return;
|
||||
|
||||
QString strToFilter;
|
||||
ui->countLabel->setText("Updating...");
|
||||
ui->tableWidget->setSortingEnabled(false);
|
||||
ui->tableWidget->clearContents();
|
||||
ui->tableWidget->setRowCount(0);
|
||||
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:%S", mn.lastPing.sigTime)));
|
||||
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->tableWidget->insertRow(0);
|
||||
ui->tableWidget->setItem(0, 0, addressItem);
|
||||
ui->tableWidget->setItem(0, 1, protocolItem);
|
||||
ui->tableWidget->setItem(0, 2, statusItem);
|
||||
ui->tableWidget->setItem(0, 3, activeSecondsItem);
|
||||
ui->tableWidget->setItem(0, 4, lastSeenItem);
|
||||
ui->tableWidget->setItem(0, 5, pubkeyItem);
|
||||
}
|
||||
|
||||
ui->countLabel->setText(QString::number(ui->tableWidget->rowCount()));
|
||||
ui->tableWidget->setSortingEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
void MasternodeList::on_filterLineEdit_textChanged(const QString &filterString) {
|
||||
strCurrentFilter = filterString;
|
||||
ui->countLabel->setText("Please wait...");
|
||||
}
|
||||
|
||||
void MasternodeList::on_startButton_clicked()
|
||||
{
|
||||
// Find selected node alias
|
||||
QItemSelectionModel* selectionModel = ui->tableWidget_2->selectionModel();
|
||||
QModelIndexList selected = selectionModel->selectedRows();
|
||||
if(selected.count() == 0)
|
||||
return;
|
||||
|
||||
QModelIndex index = selected.at(0);
|
||||
int r = index.row();
|
||||
std::string strAlias = ui->tableWidget_2->item(r, 0)->text().toStdString();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
|
||||
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForAnonymizationOnly)
|
||||
{
|
||||
WalletModel::UnlockContext ctx(walletModel->requestUnlock(true));
|
||||
if(!ctx.isValid())
|
||||
{
|
||||
// Unlock wallet was cancelled
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
|
||||
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForAnonymizationOnly)
|
||||
{
|
||||
WalletModel::UnlockContext ctx(walletModel->requestUnlock(true));
|
||||
if(!ctx.isValid())
|
||||
{
|
||||
// Unlock wallet was cancelled
|
||||
return;
|
||||
}
|
||||
StartAll();
|
||||
return;
|
||||
}
|
||||
|
||||
StartAll();
|
||||
}
|
||||
|
||||
void MasternodeList::on_startMissingButton_clicked()
|
||||
{
|
||||
|
||||
if(masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_LIST ||
|
||||
masternodeSync.RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED) {
|
||||
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;
|
||||
}
|
||||
|
||||
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
|
||||
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForAnonymizationOnly)
|
||||
{
|
||||
WalletModel::UnlockContext ctx(walletModel->requestUnlock(true));
|
||||
if(!ctx.isValid())
|
||||
{
|
||||
// Unlock wallet was cancelled
|
||||
return;
|
||||
}
|
||||
StartAll("start-missing");
|
||||
return;
|
||||
}
|
||||
|
||||
StartAll("start-missing");
|
||||
}
|
||||
|
||||
void MasternodeList::on_tableWidget_2_itemSelectionChanged()
|
||||
{
|
||||
if(ui->tableWidget_2->selectedItems().count() > 0)
|
||||
{
|
||||
ui->startButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MasternodeList::on_UpdateButton_clicked()
|
||||
{
|
||||
updateMyNodeList(true);
|
||||
}
|
63
src/qt/masternodelist.h
Normal file
63
src/qt/masternodelist.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef MASTERNODELIST_H
|
||||
#define MASTERNODELIST_H
|
||||
|
||||
#include "masternode.h"
|
||||
#include "platformstyle.h"
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#define MASTERNODELIST_UPDATE_SECONDS 5
|
||||
#define MY_MASTERNODELIST_UPDATE_SECONDS 60
|
||||
|
||||
namespace Ui {
|
||||
class MasternodeList;
|
||||
}
|
||||
|
||||
class ClientModel;
|
||||
class WalletModel;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/** Masternode Manager page widget */
|
||||
class MasternodeList : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MasternodeList(const PlatformStyle *platformStyle, QWidget *parent = 0);
|
||||
~MasternodeList();
|
||||
|
||||
void setClientModel(ClientModel *clientModel);
|
||||
void setWalletModel(WalletModel *walletModel);
|
||||
void StartAlias(std::string strAlias);
|
||||
void StartAll(std::string strCommand = "start-all");
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateMyMasternodeInfo(QString alias, QString addr, QString privkey, QString txHash, QString txIndex, CMasternode *pmn);
|
||||
void updateMyNodeList(bool reset = false);
|
||||
void updateNodeList();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
private:
|
||||
QTimer *timer;
|
||||
Ui::MasternodeList *ui;
|
||||
ClientModel *clientModel;
|
||||
WalletModel *walletModel;
|
||||
CCriticalSection cs_mnlistupdate;
|
||||
QString strCurrentFilter;
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_filterLineEdit_textChanged(const QString &filterString);
|
||||
void on_startButton_clicked();
|
||||
void on_startAllButton_clicked();
|
||||
void on_startMissingButton_clicked();
|
||||
void on_tableWidget_2_itemSelectionChanged();
|
||||
void on_UpdateButton_clicked();
|
||||
};
|
||||
#endif // MASTERNODELIST_H
|
@ -120,6 +120,13 @@ void WalletFrame::gotoHistoryPage()
|
||||
i.value()->gotoHistoryPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoMasternodePage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoMasternodePage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoReceiveCoinsPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
|
@ -55,6 +55,8 @@ public Q_SLOTS:
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to masternode page */
|
||||
void gotoMasternodePage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "bitcoingui.h"
|
||||
#include "clientmodel.h"
|
||||
#include "guiutil.h"
|
||||
#include "masternodeconfig.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "overviewpage.h"
|
||||
#include "platformstyle.h"
|
||||
@ -70,6 +71,9 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
|
||||
receiveCoinsPage = new ReceiveCoinsDialog(platformStyle);
|
||||
sendCoinsPage = new SendCoinsDialog(platformStyle);
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeListPage = new MasternodeList(platformStyle);
|
||||
}
|
||||
|
||||
usedSendingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
|
||||
usedReceivingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
|
||||
@ -78,6 +82,9 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
addWidget(transactionsPage);
|
||||
addWidget(receiveCoinsPage);
|
||||
addWidget(sendCoinsPage);
|
||||
if (masternodeConfig.getCount()) {
|
||||
addWidget(masternodeListPage);
|
||||
}
|
||||
|
||||
// Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
|
||||
@ -93,6 +100,10 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
|
||||
// Pass through messages from sendCoinsPage
|
||||
connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
|
||||
if (masternodeConfig.getCount()) {
|
||||
// Pass through messages from masternodeListPage
|
||||
connect(masternodeListPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
|
||||
}
|
||||
// Pass through messages from transactionView
|
||||
connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
|
||||
}
|
||||
@ -125,6 +136,9 @@ void WalletView::setClientModel(ClientModel *clientModel)
|
||||
|
||||
overviewPage->setClientModel(clientModel);
|
||||
sendCoinsPage->setClientModel(clientModel);
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeListPage->setClientModel(clientModel);
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::setWalletModel(WalletModel *walletModel)
|
||||
@ -134,6 +148,9 @@ void WalletView::setWalletModel(WalletModel *walletModel)
|
||||
// Put transaction list in tabs
|
||||
transactionView->setModel(walletModel);
|
||||
overviewPage->setWalletModel(walletModel);
|
||||
if (masternodeConfig.getCount()) {
|
||||
masternodeListPage->setWalletModel(walletModel);
|
||||
}
|
||||
receiveCoinsPage->setModel(walletModel);
|
||||
sendCoinsPage->setModel(walletModel);
|
||||
usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel());
|
||||
@ -190,6 +207,13 @@ void WalletView::gotoHistoryPage()
|
||||
setCurrentWidget(transactionsPage);
|
||||
}
|
||||
|
||||
void WalletView::gotoMasternodePage()
|
||||
{
|
||||
if (masternodeConfig.getCount()) {
|
||||
setCurrentWidget(masternodeListPage);
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::gotoReceiveCoinsPage()
|
||||
{
|
||||
setCurrentWidget(receiveCoinsPage);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define BITCOIN_QT_WALLETVIEW_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "masternodelist.h"
|
||||
|
||||
#include <QStackedWidget>
|
||||
|
||||
@ -65,6 +66,7 @@ private:
|
||||
SendCoinsDialog *sendCoinsPage;
|
||||
AddressBookPage *usedSendingAddressesPage;
|
||||
AddressBookPage *usedReceivingAddressesPage;
|
||||
MasternodeList *masternodeListPage;
|
||||
|
||||
TransactionView *transactionView;
|
||||
|
||||
@ -77,6 +79,8 @@ public Q_SLOTS:
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to masternode page */
|
||||
void gotoMasternodePage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "config/dash-config.h"
|
||||
#endif
|
||||
|
||||
#include "tinyformat.h"
|
||||
#include "utiltime.h"
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
@ -81,3 +82,18 @@ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
|
||||
ss << boost::posix_time::from_time_t(nTime);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DurationToDHMS(int64_t nDurationTime)
|
||||
{
|
||||
int seconds = nDurationTime % 60;
|
||||
nDurationTime /= 60;
|
||||
int minutes = nDurationTime % 60;
|
||||
nDurationTime /= 60;
|
||||
int hours = nDurationTime % 24;
|
||||
int days = nDurationTime / 24;
|
||||
if(days)
|
||||
return strprintf("%dd %02dh:%02dm:%02ds", days, hours, minutes, seconds);
|
||||
if(hours)
|
||||
return strprintf("%02dh:%02dm:%02ds", hours, minutes, seconds);
|
||||
return strprintf("%02dm:%02ds", minutes, seconds);
|
||||
}
|
||||
|
@ -17,5 +17,6 @@ void SetMockTime(int64_t nMockTimeIn);
|
||||
void MilliSleep(int64_t n);
|
||||
|
||||
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime);
|
||||
std::string DurationToDHMS(int64_t nDurationTime);
|
||||
|
||||
#endif // BITCOIN_UTILTIME_H
|
||||
|
Loading…
Reference in New Issue
Block a user