From 3764e6869ad67ff75e7928ebe06c28cba667e250 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 11 May 2016 14:09:31 +0300 Subject: [PATCH] Add masternode tab in qt wallet --- src/Makefile.qt.include | 4 + src/qt/bitcoingui.cpp | 35 ++++ src/qt/bitcoingui.h | 4 + src/qt/forms/masternodelist.ui | 317 ++++++++++++++++++++++++++++ src/qt/masternodelist.cpp | 370 +++++++++++++++++++++++++++++++++ src/qt/masternodelist.h | 63 ++++++ src/qt/walletframe.cpp | 7 + src/qt/walletframe.h | 2 + src/qt/walletview.cpp | 24 +++ src/qt/walletview.h | 4 + src/utiltime.cpp | 16 ++ src/utiltime.h | 1 + 12 files changed, 847 insertions(+) create mode 100644 src/qt/forms/masternodelist.ui create mode 100644 src/qt/masternodelist.cpp create mode 100644 src/qt/masternodelist.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 5ac0335ca..d27c5ed87 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -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 \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index abd22bc9e..ed7f5bf56 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -31,6 +31,8 @@ #include "ui_interface.h" #include "util.h" #include "masternode-sync.h" +#include "masternodeconfig.h" +#include "masternodelist.h" #include @@ -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); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index fcbb8f4d3..f9076436a 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -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 */ diff --git a/src/qt/forms/masternodelist.ui b/src/qt/forms/masternodelist.ui new file mode 100644 index 000000000..0ffe57539 --- /dev/null +++ b/src/qt/forms/masternodelist.ui @@ -0,0 +1,317 @@ + + + MasternodeList + + + + 0 + 0 + 723 + 457 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + + My masternodes + + + + + + 0 + + + + + 0 + + + + + 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. + + + + + + + + + + 695 + 0 + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + + Alias + + + + + IP/Onion + + + + + Protocol + + + + + Status + + + + + Active (secs) + + + + + Last Seen (UTC) + + + + + Pubkey + + + + + + + + 0 + + + + + S&tart alias + + + + + + + Start &all + + + + + + + Start &MISSING + + + + + + + &Update status + + + + + + + Status will be updated automatically in (sec): + + + + + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + All masternodes + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SelectRows + + + true + + + true + + + + Address + + + + + Protocol + + + + + Status + + + + + Active (secs) + + + + + Last Seen (UTC) + + + + + Pubkey + + + + + + + + 0 + + + + + Filter List: + + + + + + + Filter masternode list + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + + Node Count: + + + + + + + 0 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp new file mode 100644 index 000000000..d56de2227 --- /dev/null +++ b/src/qt/masternodelist.cpp @@ -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 +#include + +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 += "
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 += "
Successfully started masternode." ; + mnodeman.UpdateMasternodeList(mnb); + mnb.Relay(); + } else { + statusObj += "
Failed to start masternode.
Error: " + errorMessage; + } + break; + } + } + statusObj += "
"; + + 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 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); +} diff --git a/src/qt/masternodelist.h b/src/qt/masternodelist.h new file mode 100644 index 000000000..57958796a --- /dev/null +++ b/src/qt/masternodelist.h @@ -0,0 +1,63 @@ +#ifndef MASTERNODELIST_H +#define MASTERNODELIST_H + +#include "masternode.h" +#include "platformstyle.h" +#include "sync.h" +#include "util.h" + +#include +#include + +#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 diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 1b9426a4f..0ada6bb8a 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -120,6 +120,13 @@ void WalletFrame::gotoHistoryPage() i.value()->gotoHistoryPage(); } +void WalletFrame::gotoMasternodePage() +{ + QMap::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoMasternodePage(); +} + void WalletFrame::gotoReceiveCoinsPage() { QMap::const_iterator i; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 8a7776e58..49a7a6167 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -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 */ diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index a2635cd89..218839b05 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -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); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index fe726e66b..22949a639 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -6,6 +6,7 @@ #define BITCOIN_QT_WALLETVIEW_H #include "amount.h" +#include "masternodelist.h" #include @@ -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 */ diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 6252a992c..f1143e8ef 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -7,6 +7,7 @@ #include "config/dash-config.h" #endif +#include "tinyformat.h" #include "utiltime.h" #include @@ -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); +} diff --git a/src/utiltime.h b/src/utiltime.h index b2807267d..041b45862 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -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