X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fclientmodel.cpp;h=ec66cc30fe01a3db56bdeafaec9184a0e3a7e361;hb=532b9005ab4fc02db3db424b4631fe395e0b9071;hp=e39bb7ecb1d601bb012014ffe09e9f3b861d9bd7;hpb=38deedc1b52e915f2eac733e0fd7f5112361241b;p=novacoin.git diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e39bb7e..ec66cc3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -1,35 +1,65 @@ #include "clientmodel.h" -#include "main.h" #include "guiconstants.h" #include "optionsmodel.h" #include "addresstablemodel.h" #include "transactiontablemodel.h" +#include "alert.h" +#include "main.h" +#include "ui_interface.h" + +#include #include -ClientModel::ClientModel(QObject *parent) : - QObject(parent), optionsModel(0), addressTableModel(0), - transactionTableModel(0) +extern double GetPoSKernelPS(); +extern double GetDifficulty(const CBlockIndex* blockindex); + +static const int64_t nClientStartupTime = GetTime(); + +ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : + QObject(parent), optionsModel(optionsModel), + cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0) +{ + numBlocksAtStartup = -1; + + pollTimer = new QTimer(this); + pollTimer->setInterval(MODEL_UPDATE_DELAY); + pollTimer->start(); + connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); + + subscribeToCoreSignals(); +} + +ClientModel::~ClientModel() { - // Until signal notifications is built into the bitcoin core, - // simply update everything after polling using a timer. - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(MODEL_UPDATE_DELAY); + unsubscribeFromCoreSignals(); +} - optionsModel = new OptionsModel(this); - addressTableModel = new AddressTableModel(this); - transactionTableModel = new TransactionTableModel(this); +double ClientModel::getPoSKernelPS() +{ + return GetPoSKernelPS(); } -qint64 ClientModel::getBalance() const +double ClientModel::getDifficulty(bool fProofofStake) { - return GetBalance(); + if (fProofofStake) + return GetDifficulty(GetLastBlockIndex(pindexBest,true)); + else + return GetDifficulty(GetLastBlockIndex(pindexBest,false)); } -int ClientModel::getNumConnections() const +int ClientModel::getNumConnections(uint8_t flags) const { - return vNodes.size(); + LOCK(cs_vNodes); + if (flags == CONNECTIONS_ALL) // Shortcut if we want total + return (int)(vNodes.size()); + + int nNum = 0; + BOOST_FOREACH(CNode* pnode, vNodes) + if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) + nNum++; + + return nNum; } int ClientModel::getNumBlocks() const @@ -37,84 +67,75 @@ int ClientModel::getNumBlocks() const return nBestHeight; } -int ClientModel::getNumTransactions() const +int ClientModel::getNumBlocksAtStartup() { - int numTransactions = 0; - CRITICAL_BLOCK(cs_mapWallet) - { - numTransactions = mapWallet.size(); - } - return numTransactions; + if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks(); + return numBlocksAtStartup; } -void ClientModel::update() +quint64 ClientModel::getTotalBytesRecv() const { - // Plainly emit all signals for now. To be more efficient this should check - // whether the values actually changed first, although it'd be even better if these - // were events coming in from the bitcoin core. - emit balanceChanged(getBalance()); - emit numConnectionsChanged(getNumConnections()); - emit numBlocksChanged(getNumBlocks()); - emit numTransactionsChanged(getNumTransactions()); + return CNode::GetTotalBytesRecv(); +} - addressTableModel->update(); +quint64 ClientModel::getTotalBytesSent() const +{ + return CNode::GetTotalBytesSent(); } -ClientModel::StatusCode ClientModel::sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs) +QDateTime ClientModel::getLastBlockDate() const { - uint160 hash160 = 0; - bool valid = false; + if (pindexBest) + return QDateTime::fromTime_t(pindexBest->GetBlockTime()); + else + return QDateTime::fromTime_t(1360105017); // Genesis block's time +} - if(!AddressToHash160(payTo.toUtf8().constData(), hash160)) - { - return InvalidAddress; - } +void ClientModel::updateTimer() +{ + // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. + // Periodically check and update with a timer. + int newNumBlocks = getNumBlocks(); + int newNumBlocksOfPeers = getNumBlocksOfPeers(); - if(payAmount <= 0) + if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers) { - return InvalidAmount; - } + cachedNumBlocks = newNumBlocks; + cachedNumBlocksOfPeers = newNumBlocksOfPeers; - if(payAmount > getBalance()) - { - return AmountExceedsBalance; + emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers); } - if((payAmount + nTransactionFee) > getBalance()) - { - return AmountWithFeeExceedsBalance; - } + emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); +} - CRITICAL_BLOCK(cs_main) - { - // Send to bitcoin address - CWalletTx wtx; - CScript scriptPubKey; - scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; +void ClientModel::updateNumConnections(int numConnections) +{ + emit numConnectionsChanged(numConnections); +} - std::string strError = SendMoney(scriptPubKey, payAmount, wtx, true); - if (strError == "") - { - // OK - } - else if (strError == "ABORTED") - { - return Aborted; - } - else +void ClientModel::updateAlert(const QString &hash, int status) +{ + // Show error message notification for new alert + if(status == CT_NEW) + { + uint256 hash_256; + hash_256.SetHex(hash.toStdString()); + CAlert alert = CAlert::getAlertByHash(hash_256); + if(!alert.IsNull()) { - emit error(tr("Sending..."), QString::fromStdString(strError)); - return MiscError; + emit error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false); } } - // Add addresses that we've sent to to the address book - std::string strAddress = payTo.toStdString(); - CRITICAL_BLOCK(cs_mapAddressBook) - if (!mapAddressBook.count(strAddress)) - SetAddressBookName(strAddress, addToAddressBookAs.toStdString()); + // Emit a numBlocksChanged when the status message changes, + // so that the view recomputes and updates the status bar. + emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers()); +} - return OK; +bool ClientModel::isTestNet() const +{ + return fTestNet; } bool ClientModel::inInitialBlockDownload() const @@ -122,23 +143,75 @@ bool ClientModel::inInitialBlockDownload() const return IsInitialBlockDownload(); } -int ClientModel::getTotalBlocksEstimate() const +int ClientModel::getNumBlocksOfPeers() const { - return GetTotalBlocksEstimate(); + return GetNumBlocksOfPeers(); } +QString ClientModel::getStatusBarWarnings() const +{ + return QString::fromStdString(GetWarnings("statusbar")); +} OptionsModel *ClientModel::getOptionsModel() { return optionsModel; } -AddressTableModel *ClientModel::getAddressTableModel() +QString ClientModel::formatFullVersion() const +{ + return QString::fromStdString(FormatFullVersion()); +} + +QString ClientModel::formatBuildDate() const +{ + return QString::fromStdString(CLIENT_DATE); +} + +QString ClientModel::clientName() const +{ + return QString::fromStdString(CLIENT_NAME); +} + +QString ClientModel::formatClientStartupTime() const +{ + return QDateTime::fromTime_t(nClientStartupTime).toString(); +} + +// Handlers for core signals +static void NotifyBlocksChanged(ClientModel *clientmodel) +{ + // This notification is too frequent. Don't trigger a signal. + // Don't remove it, though, as it might be useful later. +} + +static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections) +{ + // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections); + QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, + Q_ARG(int, newNumConnections)); +} + +static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) +{ + OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status); + QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status)); +} + +void ClientModel::subscribeToCoreSignals() { - return addressTableModel; + // Connect signals to client + uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); } -TransactionTableModel *ClientModel::getTransactionTableModel() +void ClientModel::unsubscribeFromCoreSignals() { - return transactionTableModel; + // Disconnect signals from client + uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); }