From 26dd2c88dd592a4f0d0cce91b4db682f8755c29b Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Fri, 3 Oct 2014 02:03:43 -0700 Subject: [PATCH 001/141] fix version --- src/rpcmisc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index fcf822572f4c8..811c02fac9fa5 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -60,7 +60,7 @@ Value getinfo(const Array& params, bool fHelp) GetProxy(NET_IPV4, proxy); Object obj; - obj.push_back(Pair("mastercoreversion", (int)1030008)); // strip the initial '10' : for tagged release go to 10007, etc. + obj.push_back(Pair("mastercoreversion", (int)1030009)); // strip the initial '10' : for tagged release go to 10007, etc. obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); #ifdef ENABLE_WALLET From 886accb02a25843d499e656a0f34fbf99c9fa46c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 15:07:16 -0700 Subject: [PATCH 002/141] SP UI start to 0.0.9 --- src/qt/Makefile.am | 5 + src/qt/bitcoin.qrc | 3 +- src/qt/bitcoingui.cpp | 25 +- src/qt/bitcoingui.h | 3 + src/qt/forms/lookupspdialog.ui | 752 +++++++++++++++++++++++++++++++++ src/qt/lookupspdialog.cpp | 246 +++++++++++ src/qt/lookupspdialog.h | 53 +++ src/qt/res/icons/mp_sp.png | Bin 0 -> 1949 bytes src/qt/walletframe.cpp | 7 + src/qt/walletframe.h | 2 + src/qt/walletview.cpp | 21 +- src/qt/walletview.h | 5 + 12 files changed, 1115 insertions(+), 7 deletions(-) create mode 100644 src/qt/forms/lookupspdialog.ui create mode 100644 src/qt/lookupspdialog.cpp create mode 100644 src/qt/lookupspdialog.h create mode 100644 src/qt/res/icons/mp_sp.png diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index d5d3034b4f5fe..fb70721b5ce57 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -101,6 +101,7 @@ QT_FORMS_UI = \ forms/sendcoinsdialog.ui \ forms/sendcoinsentry.ui \ forms/sendmpdialog.ui \ + forms/lookupspdialog.ui \ forms/signverifymessagedialog.ui \ forms/transactiondescdialog.ui @@ -137,6 +138,7 @@ QT_MOC_CPP = \ moc_sendcoinsdialog.cpp \ moc_sendcoinsentry.cpp \ moc_sendmpdialog.cpp \ + moc_lookupspdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ moc_trafficgraphwidget.cpp \ @@ -203,6 +205,7 @@ BITCOIN_QT_H = \ sendcoinsdialog.h \ sendcoinsentry.h \ sendmpdialog.h \ + lookupspdialog.h \ signverifymessagedialog.h \ splashscreen.h \ trafficgraphwidget.h \ @@ -221,6 +224,7 @@ BITCOIN_QT_H = \ winshutdownmonitor.h RES_ICONS = \ + res/icons/mp_sp.png \ res/icons/mp_balances.png \ res/icons/mp_history.png \ res/icons/mp_home.png \ @@ -310,6 +314,7 @@ BITCOIN_QT_CPP += \ sendcoinsdialog.cpp \ sendcoinsentry.cpp \ sendmpdialog.cpp \ + lookupspdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ transactiondescdialog.cpp \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index f84140dcac521..1ebcc8e5ee390 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,6 +1,7 @@ - res/icons/mp_balances.png + res/icons/mp_balances.png + res/icons/mp_sp.png res/icons/bitcoin.png res/icons/address-book.png res/icons/quit.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index ebf6e71c007b7..2aef9ecc7a04d 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -234,7 +234,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) tabGroup->addAction(balancesAction); sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this); - sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address")); + sendCoinsAction->setStatusTip(tr("Send Master Protocol and Bitcoin transactions")); sendCoinsAction->setToolTip(sendCoinsAction->statusTip()); sendCoinsAction->setCheckable(true); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); @@ -247,11 +247,18 @@ void BitcoinGUI::createActions(bool fIsTestnet) receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(receiveCoinsAction); + smartPropertyAction = new QAction(QIcon(":/icons/smartproperty"), tr("Smart &Property"), this); + smartPropertyAction->setStatusTip(tr("Lookup and interact with Master Protocol Smart Properties")); + smartPropertyAction->setToolTip(smartPropertyAction->statusTip()); + smartPropertyAction->setCheckable(true); + smartPropertyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); + tabGroup->addAction(smartPropertyAction); + historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setToolTip(historyAction->statusTip()); historyAction->setCheckable(true); - historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); + historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); tabGroup->addAction(historyAction); // These showNormalIfMinimized are needed because Send Coins and Receive Coins @@ -264,6 +271,8 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); + connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(gotoSmartPropertyPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); @@ -395,6 +404,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(balancesAction); toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); + toolbar->addAction(smartPropertyAction); toolbar->addAction(historyAction); overviewAction->setChecked(true); } @@ -460,6 +470,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) balancesAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); + smartPropertyAction->setEnabled(enabled); historyAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled); @@ -478,12 +489,12 @@ void BitcoinGUI::createTrayIcon(bool fIsTestnet) if (!fIsTestnet) { - trayIcon->setToolTip(tr("Bitcoin client")); + trayIcon->setToolTip(tr("Mastercore client")); trayIcon->setIcon(QIcon(":/icons/toolbar")); } else { - trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]")); + trayIcon->setToolTip(tr("Mastercore client") + " " + tr("[testnet]")); trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); } @@ -608,6 +619,12 @@ void BitcoinGUI::gotoSendCoinsPage(QString addr) if (walletFrame) walletFrame->gotoSendCoinsPage(addr); } +void BitcoinGUI::gotoSmartPropertyPage() +{ + smartPropertyAction->setChecked(true); + if (walletFrame) walletFrame->gotoSmartPropertyPage(); +} + void BitcoinGUI::gotoSignMessageTab(QString addr) { if (walletFrame) walletFrame->gotoSignMessageTab(addr); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b05646d22779d..3db27155d7b45 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -80,6 +80,7 @@ class BitcoinGUI : public QMainWindow QAction *historyAction; QAction *quitAction; QAction *sendCoinsAction; + QAction *smartPropertyAction; QAction *usedSendingAddressesAction; QAction *usedReceivingAddressesAction; QAction *signMessageAction; @@ -163,6 +164,8 @@ private slots: void gotoBalancesPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); + /** Switch to the smart property page */ + void gotoSmartPropertyPage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); /** Switch to send coins page */ diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui new file mode 100644 index 0000000000000..072dd8256472d --- /dev/null +++ b/src/qt/forms/lookupspdialog.ui @@ -0,0 +1,752 @@ + + + LookupSPDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + true + + + + 130 + 0 + + + + Search Smart Property: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + + + Search + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + 0 + + + + + + 130 + 0 + + + + Matching Results: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + 75 + true + + + + Smart Property Information + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + + + 0 + + + + + Property ID: + + + + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + -1 + + + + + + + + + Name: + + + + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Category: + + + + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Subcategory: + + + + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + URL: + + + + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Data: + + + + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + <b>Token Information</b> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + + + + 75 + true + + + + Fixed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Test + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Qt::LeftToRight + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + No + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Divisible: + + + + + + + Issuance Type: + + + + + + + Ecosystem: + + + + + + + Total Tokens: + + + + + + + Wallet Balance: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 12 + + + + + + 75 + true + + + + Crowdsale Information + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 0 + + + + + Desired Property: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Tokens Per Unit: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Deadline: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Estimated Bonus: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer Percentage: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Purchase + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp new file mode 100644 index 0000000000000..a5fe361c3e535 --- /dev/null +++ b/src/qt/lookupspdialog.cpp @@ -0,0 +1,246 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "lookupspdialog.h" +#include "ui_lookupspdialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace json_spirit; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" + +#include +#include +#include + +LookupSPDialog::LookupSPDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LookupSPDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; + + // populate placeholder text + ui->searchLineEdit->setPlaceholderText("Search property ID, issuer or property name"); + + // connect actions + connect(ui->matchingComboBox, SIGNAL(activated(int)), this, SLOT(matchingComboBoxChanged(int))); + connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); +} + +void LookupSPDialog::searchSP() +{ + // search function to lookup properties, we want this search function to be as capable as possible to + // help users find the property they're looking for via search terms they may want to use +printf("search\n"); + int searchParamType = 0; + string searchText = ui->searchLineEdit->text().toStdString(); + unsigned int searchPropertyId = 0; + + // first let's check if we have a searchText, if not do nothing + if (searchText.empty()) return; + + // try seeing if we have a numerical search string, if so treat it as a property ID search + try + { + searchPropertyId = boost::lexical_cast(searchText); + searchParamType = 1; // search by propertyId + } + catch(const boost::bad_lexical_cast &e) { } + if (searchParamType == 1 && 0 >= searchPropertyId) searchParamType = 0; // we got a number but it's <=0 + + // next if not positive numerical, lets see if the string is a valid bitcoin address + if (searchParamType == 0) + { + CBitcoinAddress address; + address.SetString(searchText); // no null check on searchText required we've already checked it's not empty above + if (address.IsValid()) searchParamType = 2; // search by address; + } + + // if we still don't have a param we'll search against free text in the name + if (searchParamType == 0) searchParamType = 3; // search by free text +printf("selected search type is %d\n", searchParamType); + + // clear matching results combo + ui->matchingComboBox->clear(); + bool spExists; + unsigned int tmpPropertyId; + unsigned int nextSPID; + unsigned int nextTestSPID; + unsigned int propertyId; + QString strId; + switch(searchParamType) + { + case 1: //search by property Id + // convert search string to ID + strId = QString::fromStdString(searchText); + propertyId = strId.toUInt(); + // check if this property ID exists, if not no match to populate and just return + spExists = _my_sps->hasSP(propertyId); + if (spExists) + { + addSPToMatchingResults(propertyId); + updateDisplayedProperty(); + } + else + { + return; + } + break; + case 2: //search by address + // iterate through my_sps looking for the issuer address and add any properties issued by said address to matchingcombo + // talk with @Michael @Bart to see if perhaps a more efficient way to do this, but not major issue as only run on user request + nextSPID = _my_sps->peekNextSPID(1); + nextTestSPID = _my_sps->peekNextSPID(2); + for (tmpPropertyId = 1; tmpPropertyIdgetSP(tmpPropertyId, sp)) + { + if (sp.issuer == searchText) + { + addSPToMatchingResults(tmpPropertyId); + } + } + } + for (tmpPropertyId = TEST_ECO_PROPERTY_1; tmpPropertyIdgetSP(tmpPropertyId, sp)) + { + if (sp.issuer == searchText) + { + addSPToMatchingResults(tmpPropertyId); + } + } + } + break; + case 3: //search by freetext + // iterate through my_sps and see if property name contains the search text + break; + } + +} + +void LookupSPDialog::addSPToMatchingResults(unsigned int propertyId) +{ + // verify the supplied property exists (sanity check) then populate the matching results combo box + bool spExists = _my_sps->hasSP(propertyId); + if (spExists) + { + string spName; + spName = getPropertyName(propertyId).c_str(); + if(spName.size()>30) spName=spName.substr(0,30)+"..."; + string spId = static_cast( &(ostringstream() << propertyId) )->str(); + spName += " (#" + spId + ")"; + ui->matchingComboBox->addItem(spName.c_str(),spId.c_str()); + } + else + { + return; + } +} + +void LookupSPDialog::updateDisplayedProperty() +{ + QString strId = ui->matchingComboBox->itemData(ui->matchingComboBox->currentIndex()).toString(); + // protect against an empty matchedComboBox + if (strId.toStdString().empty()) return; + + // map property Id + unsigned int propertyId = strId.toUInt(); + CMPSPInfo::Entry sp; + if (false == _my_sps->getSP(propertyId, sp)) { return; } // something has gone wrong, don't attempt to display non-existent property + + // populate the fields + bool divisible=sp.isDivisible(); + if (divisible) { ui->divisibleLabel->setText("Yes"); } else { ui->divisibleLabel->setText("No"); } + if (propertyId>2147483647) { ui->ecosystemLabel->setText("Test"); } else { ui->ecosystemLabel->setText("Production"); } + ui->propertyIDLabel->setText(QString::fromStdString(FormatIndivisibleMP(propertyId))); + ui->nameLabel->setText(QString::fromStdString(sp.name)); + ui->categoryLabel->setText(QString::fromStdString(sp.category)); + ui->subcategoryLabel->setText(QString::fromStdString(sp.subcategory)); + ui->dataLabel->setText(QString::fromStdString(sp.data)); + ui->urlLabel->setText(QString::fromStdString(sp.url)); + string strTotalTokens; + string strWalletTokens; + int64_t totalTokens = getTotalTokens(propertyId); + int64_t walletTokens = 0; + if (propertyId<2147483648) + { walletTokens = global_balance_money_maineco[propertyId]; } + else + { walletTokens = global_balance_money_testeco[propertyId-2147483647]; } + string tokenLabel; + if (propertyId > 2) + { + tokenLabel = " SPT"; + } + else + { + if (propertyId == 1) { tokenLabel = " MSC"; } else { tokenLabel = " TMSC"; } + } + if (divisible) { strTotalTokens = FormatDivisibleMP(totalTokens); } else { strTotalTokens = FormatIndivisibleMP(totalTokens); } + if (divisible) { strWalletTokens = FormatDivisibleMP(walletTokens); } else { strWalletTokens = FormatIndivisibleMP(walletTokens); } + ui->totalTokensLabel->setText(QString::fromStdString(strTotalTokens + tokenLabel)); + ui->walletBalanceLabel->setText(QString::fromStdString(strWalletTokens + tokenLabel)); + ui->issuerLabel->setText(QString::fromStdString(sp.issuer)); + // issuances are no longer just fixed or variable, this needs further code changes to sp.fixed + //bool fixedIssuance = sp.fixed; +} + +void LookupSPDialog::searchButtonClicked() +{ + searchSP(); +} + +void LookupSPDialog::matchingComboBoxChanged(int idx) +{ + updateDisplayedProperty(); +} diff --git a/src/qt/lookupspdialog.h b/src/qt/lookupspdialog.h new file mode 100644 index 0000000000000..c672eb330844b --- /dev/null +++ b/src/qt/lookupspdialog.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef LOOKUPSPDIALOG_H +#define LOOKUPSPDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class LookupSPDialog; +} + +/** Dialog for looking up Master Protocol tokens */ +class LookupSPDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LookupSPDialog(QWidget *parent = 0); + void searchSP(); + void updateDisplayedProperty(); + void addSPToMatchingResults(unsigned int); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + +public slots: + void searchButtonClicked(); + void matchingComboBoxChanged(int); + +private: + Ui::LookupSPDialog *ui; + WalletModel *model; + +//private slots: + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // LOOKUPSPDIALOG_H diff --git a/src/qt/res/icons/mp_sp.png b/src/qt/res/icons/mp_sp.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3c728dc6a488879ca928e3f475070cfdb2f596 GIT binary patch literal 1949 zcmV;O2V(e%P) zMU?Vf7~0G;ZaMPe{QXh8t+Nv9mXY{n`Vb1s0K z;IeHl#^&)EoT@dj^_-2XP zxH7bnD@Ak-rwSndhB@qb9Q9G4wOE@tdqKZ?{}cfOIWv30Nmc~!}2pp3A0k|q81{53WZ+g?IP6$oze?{ z$=^r57pV(ovlf8{`F@K)XGlI(`kUY=7p!E}A?OSv{~37671LQbfzF70*uJIdK!be0 zMW9C@zs9zYRiem}Ur7cXC{!^3w+$Gt~S)#2NBQkR@++xVlD?Vbqva~IF6Z@&8S zNCd8cgiQGSvq^P%@e6hD{sSX~ClaSxGu-@Y|6?;8YD-4t_`odDQYu1iIO z%eFtP*cHO{xTzqn1BmVM2St*P5T5&HCIa9`w;N)SP#yDD0K#)`Fn8$%z`K1-i=&{_ z`1F&HrBBgh4pTb-_4{=Nh}8kYsH-7+HkBdKzY3bH$LdKgP#F^axXU+i-{QP2ms>l@ z1uBUCqAO~1R^baOKfJGt*-nkH40Eqq}7bY`Y`gNM36&&pBBfs)qT-Vk^d&oD;oA-$Dju@q#p>$3!^@Gl1AI% z|2*z@fCa?9^H?}31;GB@$5NyK*#7aKyzXNve5<$u`}aEygat5_G@Ay~m0_zgG!8~`n#&#fR*08#(|0RRvH0096H000315C8xH z03HdThh^{)t?=tY&R5P`$whwVSg0gwhf zvj0c{7=@4nbg@>>q08K=VGcmJjrDR4k(>?^z?Q--VwcckPU8u{SVa#m;8yfAr?DM? zumKlvCi*u9eRH4y-~#SP|1bv#TmT(`#g+d_(LYoGtekbpD}3?twYTi#F!%M7qCbuU z1p5MQsVh7@eCMqIgy-Il>iZK5fUyDxux{?LIEy6!-ao!6ag}?Io~pyQ{<#3nndUBp zoBezKqdEYI;D!=-UVs+j-u(yO34rD-B>WC@r7{%&V^LynVDHfr$!I7YXs$G8p`L#+ z$uA@l0NaX4SMbx_U(NW<>2yGIqdC%C1*`rE?Z6 zUF58d5Ei&L@U>m+a;`7zoea9@72tM}x`b7aip1c*t~R9FJ8J~snGi}teCY(xCxm4d zf-9+^%fxS$h4|76AfiTCQuf|uq};w;WRAC50DWCUAcnH(&ckfJ4+-6yu?kkwhE;$$_OG jaFlm#i|}FiSAYQk{F8cK=-gotoBalancesPage(); } +void WalletFrame::gotoSmartPropertyPage() +{ + QMap::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoSmartPropertyPage(); +} + void WalletFrame::gotoHistoryPage() { QMap::const_iterator i; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index cd93adb595b1b..cf9bb05a206b5 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -52,6 +52,8 @@ public slots: void gotoOverviewPage(); /** Switch to balances page */ void gotoBalancesPage(); + /** Switch to smart property page */ + void gotoSmartPropertyPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); /** Switch to receive coins page */ diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index a31bc64193911..622c323dbc5be 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -14,6 +14,7 @@ #include "receivecoinsdialog.h" #include "sendcoinsdialog.h" #include "sendmpdialog.h" +#include "lookupspdialog.h" #include "signverifymessagedialog.h" #include "transactiontablemodel.h" #include "transactionview.h" @@ -90,18 +91,29 @@ WalletView::WalletView(QWidget *parent): svbox->addWidget(tabHolder); sendCoinsPage->setLayout(svbox); + // smart property page + smartPropertyPage = new QWidget(this); + QVBoxLayout *spvbox = new QVBoxLayout(); + spLookupTab = new LookupSPDialog(); + QTabWidget *spTabHolder = new QTabWidget(); + spTabHolder->addTab(spLookupTab,tr("Lookup Property")); + spTabHolder->addTab(new QWidget(),tr("Crowdsale Participation")); +// spTabHolder->addTab(new QWidget(),tr("Property Issuance")); +// spTabHolder->addTab(new QWidget(),tr("Revoke or Grant Tokens")); + spvbox->addWidget(spTabHolder); + smartPropertyPage->setLayout(spvbox); + // add pages addWidget(overviewPage); addWidget(balancesPage); addWidget(transactionsPage); addWidget(receiveCoinsPage); addWidget(sendCoinsPage); + addWidget(smartPropertyPage); // 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))); -// connect(showAllBalancesLabel, SIGNAL(clicked()), overviewPage, SLOT(WalletView::gotoBalancesPage())); - // Double-clicking on a transaction on the transaction history page shows details connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); @@ -211,6 +223,11 @@ void WalletView::gotoReceiveCoinsPage() setCurrentWidget(receiveCoinsPage); } +void WalletView::gotoSmartPropertyPage() +{ + setCurrentWidget(smartPropertyPage); +} + void WalletView::gotoSendCoinsPage(QString addr) { setCurrentWidget(sendCoinsPage); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index fc3e8b43b7891..9f69c1ed3904f 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -13,6 +13,7 @@ class OverviewPage; class ReceiveCoinsDialog; class SendCoinsDialog; class SendMPDialog; +class LookupSPDialog; class SendCoinsRecipient; class TransactionView; class BalancesView; @@ -59,12 +60,14 @@ class WalletView : public QStackedWidget OverviewPage *overviewPage; QWidget *transactionsPage; QWidget *balancesPage; + QWidget *smartPropertyPage; ReceiveCoinsDialog *receiveCoinsPage; // SendCoinsDialog *sendCoinsPage; QWidget *sendCoinsPage; SendCoinsDialog *sendCoinsTab; SendMPDialog *sendMPTab; + LookupSPDialog *spLookupTab; TransactionView *transactionView; BalancesView *balancesView; @@ -76,6 +79,8 @@ public slots: void gotoOverviewPage(); /** Switch to balances page */ void gotoBalancesPage(); + /** Switch to smart property page */ + void gotoSmartPropertyPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); /** Switch to receive coins page */ From 10c16eb2d7c4af2439f5d35848524ad7b08f9319 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 16:41:04 -0700 Subject: [PATCH 003/141] Start of Exchange UI --- src/qt/Makefile.am | 1 + src/qt/bitcoin.qrc | 1 + src/qt/bitcoingui.cpp | 21 +++++++++++++++++++-- src/qt/bitcoingui.h | 3 +++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index fb70721b5ce57..0658865630982 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -224,6 +224,7 @@ BITCOIN_QT_H = \ winshutdownmonitor.h RES_ICONS = \ + res/icons/mp_exchange.png \ res/icons/mp_sp.png \ res/icons/mp_balances.png \ res/icons/mp_history.png \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 1ebcc8e5ee390..b32915f086a58 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,6 +1,7 @@ res/icons/mp_balances.png + res/icons/mp_exchange.png res/icons/mp_sp.png res/icons/bitcoin.png res/icons/address-book.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2aef9ecc7a04d..d3fb343a42572 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -247,18 +247,25 @@ void BitcoinGUI::createActions(bool fIsTestnet) receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(receiveCoinsAction); + exchangeAction = new QAction(QIcon(":/icons/exchange"), tr("&Exchange"), this); + exchangeAction->setStatusTip(tr("Trade properties on the distributed exchange")); + exchangeAction->setToolTip(exchangeAction->statusTip()); + exchangeAction->setCheckable(true); + exchangeAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); + tabGroup->addAction(exchangeAction); + smartPropertyAction = new QAction(QIcon(":/icons/smartproperty"), tr("Smart &Property"), this); smartPropertyAction->setStatusTip(tr("Lookup and interact with Master Protocol Smart Properties")); smartPropertyAction->setToolTip(smartPropertyAction->statusTip()); smartPropertyAction->setCheckable(true); - smartPropertyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); + smartPropertyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); tabGroup->addAction(smartPropertyAction); historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setToolTip(historyAction->statusTip()); historyAction->setCheckable(true); - historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); + historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_7)); tabGroup->addAction(historyAction); // These showNormalIfMinimized are needed because Send Coins and Receive Coins @@ -273,6 +280,8 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(gotoSmartPropertyPage())); + connect(exchangeAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(exchangeAction, SIGNAL(triggered()), this, SLOT(gotoExchangePage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); @@ -404,6 +413,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(balancesAction); toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); + toolbar->addAction(exchangeAction); toolbar->addAction(smartPropertyAction); toolbar->addAction(historyAction); overviewAction->setChecked(true); @@ -470,6 +480,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) balancesAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); + exchangeAction->setEnabled(enabled); smartPropertyAction->setEnabled(enabled); historyAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); @@ -619,6 +630,12 @@ void BitcoinGUI::gotoSendCoinsPage(QString addr) if (walletFrame) walletFrame->gotoSendCoinsPage(addr); } +void BitcoinGUI::gotoExchangePage() +{ + smartPropertyAction->setChecked(true); + if (walletFrame) walletFrame->gotoSmartPropertyPage(); +} + void BitcoinGUI::gotoSmartPropertyPage() { smartPropertyAction->setChecked(true); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 3db27155d7b45..f916b5355d710 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -80,6 +80,7 @@ class BitcoinGUI : public QMainWindow QAction *historyAction; QAction *quitAction; QAction *sendCoinsAction; + QAction *exchangeAction; QAction *smartPropertyAction; QAction *usedSendingAddressesAction; QAction *usedReceivingAddressesAction; @@ -164,6 +165,8 @@ private slots: void gotoBalancesPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); + /** Switch to exchange page */ + void gotoExchangePage(); /** Switch to the smart property page */ void gotoSmartPropertyPage(); /** Switch to receive coins page */ From d278a20e5651924b7713934f5c074a0eb87b90b5 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 16:54:43 -0700 Subject: [PATCH 004/141] Exchange tabs and actions --- src/qt/bitcoingui.cpp | 4 ++-- src/qt/walletframe.cpp | 7 +++++++ src/qt/walletframe.h | 2 ++ src/qt/walletview.cpp | 15 +++++++++++++++ src/qt/walletview.h | 3 +++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index d3fb343a42572..a785b89a1cda4 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -632,8 +632,8 @@ void BitcoinGUI::gotoSendCoinsPage(QString addr) void BitcoinGUI::gotoExchangePage() { - smartPropertyAction->setChecked(true); - if (walletFrame) walletFrame->gotoSmartPropertyPage(); + exchangeAction->setChecked(true); + if (walletFrame) walletFrame->gotoExchangePage(); } void BitcoinGUI::gotoSmartPropertyPage() diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 659d463dc5727..705b805ab7354 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -119,6 +119,13 @@ void WalletFrame::gotoBalancesPage() i.value()->gotoBalancesPage(); } +void WalletFrame::gotoExchangePage() +{ + QMap::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoExchangePage(); +} + void WalletFrame::gotoSmartPropertyPage() { QMap::const_iterator i; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index cf9bb05a206b5..372217e27df70 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -52,6 +52,8 @@ public slots: void gotoOverviewPage(); /** Switch to balances page */ void gotoBalancesPage(); + /** Switch to exchange page */ + void gotoExchangePage(); /** Switch to smart property page */ void gotoSmartPropertyPage(); /** Switch to history (transactions) page */ diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 622c323dbc5be..4178a628b092f 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -91,6 +91,15 @@ WalletView::WalletView(QWidget *parent): svbox->addWidget(tabHolder); sendCoinsPage->setLayout(svbox); + // exchange page + exchangePage = new QWidget(this); + QVBoxLayout *exvbox = new QVBoxLayout(); + QTabWidget *exTabHolder = new QTabWidget(); + exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); + exTabHolder->addTab(new QWidget(),tr("Trade Mastercoin/Smart Properties")); + exvbox->addWidget(exTabHolder); + exchangePage->setLayout(exvbox); + // smart property page smartPropertyPage = new QWidget(this); QVBoxLayout *spvbox = new QVBoxLayout(); @@ -109,6 +118,7 @@ WalletView::WalletView(QWidget *parent): addWidget(transactionsPage); addWidget(receiveCoinsPage); addWidget(sendCoinsPage); + addWidget(exchangePage); addWidget(smartPropertyPage); // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page @@ -223,6 +233,11 @@ void WalletView::gotoReceiveCoinsPage() setCurrentWidget(receiveCoinsPage); } +void WalletView::gotoExchangePage() +{ + setCurrentWidget(exchangePage); +} + void WalletView::gotoSmartPropertyPage() { setCurrentWidget(smartPropertyPage); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 9f69c1ed3904f..b35d15c908cef 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -60,6 +60,7 @@ class WalletView : public QStackedWidget OverviewPage *overviewPage; QWidget *transactionsPage; QWidget *balancesPage; + QWidget *exchangePage; QWidget *smartPropertyPage; ReceiveCoinsDialog *receiveCoinsPage; @@ -79,6 +80,8 @@ public slots: void gotoOverviewPage(); /** Switch to balances page */ void gotoBalancesPage(); + /** Switch to exchange page */ + void gotoExchangePage(); /** Switch to smart property page */ void gotoSmartPropertyPage(); /** Switch to history (transactions) page */ From 7207a75de32cae37627b8569e9f4b406feb01c6a Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 18:15:44 -0700 Subject: [PATCH 005/141] Clean up --- src/qt/forms/lookupspdialog.ui | 1534 ++++++++++++++++---------------- 1 file changed, 782 insertions(+), 752 deletions(-) diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui index 072dd8256472d..a7019ed9cf36d 100644 --- a/src/qt/forms/lookupspdialog.ui +++ b/src/qt/forms/lookupspdialog.ui @@ -1,752 +1,782 @@ - - - LookupSPDialog - - - - 0 - 0 - 664 - 474 - - - - Form - - - - - - false - - - background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; - - - true - - - 3 - - - - - - - 0 - - - - - true - - - - 130 - 0 - - - - Search Smart Property: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 8 - - - - - - - - - - Search - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 20 - - - - - - - - - - 0 - - - - - - 130 - 0 - - - - Matching Results: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 8 - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 20 - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - 75 - true - - - - Smart Property Information - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - - - - - 0 - - - - - Property ID: - - - - - - - - 75 - true - - - - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Issuer: - - - - - - - - 0 - 0 - - - - - 75 - true - - - - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 - - - -1 - - - - - - - - - Name: - - - - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Category: - - - - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Subcategory: - - - - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - URL: - - - - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Data: - - - - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 20 - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - <b>Token Information</b> - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - - - - 75 - true - - - - Fixed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Test - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Qt::LeftToRight - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - No - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Divisible: - - - - - - - Issuance Type: - - - - - - - Ecosystem: - - - - - - - Total Tokens: - - - - - - - Wallet Balance: - - - - - - - - 75 - true - - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - 12 - - - - - - 75 - true - - - - Crowdsale Information - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - 0 - - - - - Desired Property: - - - - - - - - 75 - true - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Tokens Per Unit: - - - - - - - - 75 - true - - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Deadline: - - - - - - - - 75 - true - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Estimated Bonus: - - - - - - - - 75 - true - - - - 0% - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Issuer Percentage: - - - - - - - - 75 - true - - - - 0% - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Purchase - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - + + + LookupSPDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + true + + + + 130 + 0 + + + + Search Smart Property: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + + + Search + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + 0 + + + + + + 130 + 0 + + + + Matching Results: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + 75 + true + + + + Smart Property Information + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + + + 0 + + + + + Property ID: + + + + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + -1 + + + + + + + + + Name: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Category: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Subcategory: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + URL: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Data: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + <b>Token Information</b> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + + + + 75 + true + + + + Fixed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Test + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Qt::LeftToRight + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + No + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Divisible: + + + + + + + Issuance Type: + + + + + + + Ecosystem: + + + + + + + Total Tokens: + + + + + + + Wallet Balance: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 12 + + + + + + 75 + true + + + + Crowdsale Information + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 0 + + + + + Desired Property: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Tokens Per Unit: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Deadline: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Estimated Bonus: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer Percentage: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Purchase + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + From 52d10c24a9a1f3e9263a772c4192dc7dcfe4de37 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 18:16:12 -0700 Subject: [PATCH 006/141] Initial stab at metadex form --- src/qt/forms/metadex.ui | 623 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 src/qt/forms/metadex.ui diff --git a/src/qt/forms/metadex.ui b/src/qt/forms/metadex.ui new file mode 100644 index 0000000000000..32df472c4050f --- /dev/null +++ b/src/qt/forms/metadex.ui @@ -0,0 +1,623 @@ + + + LookupSPDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + + 75 + true + + + + Exchange - SP#3/MSC + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 6 + 20 + + + + + + + + true + + + + 0 + 0 + + + + Switch Markets: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0 + + + + + + + + 0 + 0 + + + + + + + + Switch + + + + + + + + + 10 + + + 0 + + + 10 + + + + + + 75 + true + + + + + + + Your Open Positions + + + + + + + + 0 + 0 + + + + + 0 + 1 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + 75 + true + + + + BUY SP#3 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Your Balance 0.000000000 MSC + + + + + + + + + 0 + + + + + Address: + + + + + + + + 0 + 0 + + + + + + + + + + 0 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 0 + + + + + Amount (SP#3): + + + + + + + + + + Price Per SP#3: + + + + + + + + + + + + 0 + + + 0 + + + + + 0 + + + 0 + + + + + SPT + + + + + + + MSC + + + + + + + + + + + + + 0 + + + + + Total Price: + + + + + + + + 75 + true + + + + 0.00000000 MSC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Buy SP#3 + + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 75 + true + + + + SELL SP#3 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Your Balance 0.000000000 SPT + + + + + + + + + 0 + + + + + Address: + + + + + + + + 0 + 0 + + + + + + + + + + 0 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + + + Amount (SP#3): + + + + + + + + + + Price Per SP#3: + + + + + + + + + + + + 0 + + + 0 + + + + + 0 + + + 0 + + + + + SPT + + + + + + + MSC + + + + + + + + + + + + + 0 + + + + + Total Price: + + + + + + + + 75 + true + + + + 0.00000000 MSC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Sell SP#3 + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + From c1bcfe8d101c0f306fac2cdd2aab02e0089c0047 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 19:19:34 -0700 Subject: [PATCH 007/141] MetaDEx base form UI --- src/qt/Makefile.am | 4 + src/qt/forms/{metadex.ui => metadexdialog.ui} | 64 +++-------- src/qt/metadexdialog.cpp | 105 ++++++++++++++++++ src/qt/metadexdialog.h | 48 ++++++++ src/qt/res/icons/mp_exchange.png | Bin 0 -> 2824 bytes src/qt/walletview.cpp | 4 +- src/qt/walletview.h | 3 +- 7 files changed, 180 insertions(+), 48 deletions(-) rename src/qt/forms/{metadex.ui => metadexdialog.ui} (90%) create mode 100644 src/qt/metadexdialog.cpp create mode 100644 src/qt/metadexdialog.h create mode 100644 src/qt/res/icons/mp_exchange.png diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 0658865630982..d0d91f5bab14a 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -101,6 +101,7 @@ QT_FORMS_UI = \ forms/sendcoinsdialog.ui \ forms/sendcoinsentry.ui \ forms/sendmpdialog.ui \ + forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/signverifymessagedialog.ui \ forms/transactiondescdialog.ui @@ -138,6 +139,7 @@ QT_MOC_CPP = \ moc_sendcoinsdialog.cpp \ moc_sendcoinsentry.cpp \ moc_sendmpdialog.cpp \ + moc_metadexdialog.cpp \ moc_lookupspdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ @@ -205,6 +207,7 @@ BITCOIN_QT_H = \ sendcoinsdialog.h \ sendcoinsentry.h \ sendmpdialog.h \ + metadexdialog.h \ lookupspdialog.h \ signverifymessagedialog.h \ splashscreen.h \ @@ -315,6 +318,7 @@ BITCOIN_QT_CPP += \ sendcoinsdialog.cpp \ sendcoinsentry.cpp \ sendmpdialog.cpp \ + metadexdialog.cpp \ lookupspdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ diff --git a/src/qt/forms/metadex.ui b/src/qt/forms/metadexdialog.ui similarity index 90% rename from src/qt/forms/metadex.ui rename to src/qt/forms/metadexdialog.ui index 32df472c4050f..dacae9eafad82 100644 --- a/src/qt/forms/metadex.ui +++ b/src/qt/forms/metadexdialog.ui @@ -1,7 +1,7 @@ - LookupSPDialog - + MetaDExDialog + 0 @@ -357,27 +357,18 @@ - + + + + 0 + 0 + + + - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 20 - - - - @@ -581,41 +572,22 @@ - + + + + 0 + 0 + + + - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp new file mode 100644 index 0000000000000..61e6400bc70be --- /dev/null +++ b/src/qt/metadexdialog.cpp @@ -0,0 +1,105 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "metadexdialog.h" +#include "ui_metadexdialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace json_spirit; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" + +#include +#include +#include + +MetaDExDialog::MetaDExDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::MetaDExDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; + +//dummy data +//ui->buyList->addItem('TEST'); +//ui->buyList->addItem('12345678901234567890'); +//ui->buyList->addItem('1234567890 1234567890 1234567890 1234567890 '); +//ui->buyList->addItem('ABCDEFGHIJ'); +//ui->buyList->addItem('ABCDEFGHIJ IKLMNOPQRS TVUWXKR333'); +//ui->buyList->addItem('TEST'); + + +ui->buyList->setColumnCount(3); +for(int i=0; i<5; ++i) { + string strprice = "349.00000006"; + string strtotal = "123456.00000001"; + string strmsctotal = "123456.00000001"; +// QListWidgetItem *item=new QListWidgetItem(QIcon(":/images/Icon.png"),QString::fromStdString(strt)); +// ui->buyList->addItem(item); +QString pstr = QString::fromStdString(strprice); +QString tstr = QString::fromStdString(strtotal); +QString mstr = QString::fromStdString(strmsctotal); + + if (!ui->buyList) { printf("metadex dialog error\n"); return; } + + const int currentRow = ui->buyList->rowCount(); + ui->buyList->setRowCount(currentRow + 1); + ui->buyList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); + ui->buyList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); + ui->buyList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); + + ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); + ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); + ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); + ui->buyList->verticalHeader()->setVisible(false); + ui->buyList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + ui->buyList->setShowGrid(false); + ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); +}} diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h new file mode 100644 index 0000000000000..f3bcc42235c73 --- /dev/null +++ b/src/qt/metadexdialog.h @@ -0,0 +1,48 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef METADEXDIALOG_H +#define METADEXDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class MetaDExDialog; +} + +/** Dialog for looking up Master Protocol tokens */ +class MetaDExDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MetaDExDialog(QWidget *parent = 0); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + +public slots: + +private: + Ui::MetaDExDialog *ui; + WalletModel *model; + +//private slots: + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // METADEXDIALOG_H diff --git a/src/qt/res/icons/mp_exchange.png b/src/qt/res/icons/mp_exchange.png new file mode 100644 index 0000000000000000000000000000000000000000..6432e7606a040191d901af834c6e84654f8706d8 GIT binary patch literal 2824 zcmeHI`#;l*8~<#~Wo4ETi6XahTq8-h$z_}vxir^ov|Ku|m`ly-<1)8a(^(|BEILY! zTTm!66r7#x zJtPeNN;xS>UE*I~l@KJx19J?he6R6Y(nyEey4nIjHDl8{0R{k4fV+#AgG6@=jPVYR z_Y0-?g(l+v0Ey>QiRWo&<1$H;iQ3)2`yY1zf; z*ID$O((C#6Zx*v}->oXRTUAp2W7K_+K4huX!OPcLI<- zu%41F`hN!Cxgx74@lT%QFoLt6)k(*vvwAv1 z>l=-zgF}o8CYx#GkG&+ucbKk_Yzp7kSR{nECg$pn6I!jE&%|iJbpyBs{(ajFMh&4b zU9(B8rg8=OEoL-%Q_lciY8!NfKc#RXrGsOsyZ~QO;H#JjdG_1@y3PJ^eeKVxyuL(7 zDfv?nVN?j6s>5IkHuy@sgkceB5|$1knnL%s85?In&(v8dSq%T3 zrmK}NI(|12DNWW$v`U49t0JpKD$D39_)Kd9i>nVzuK=4#Mo?0;DObAGgk>OB?V;S! zXW>L!VP)Wsw&H6C)D<9I-`zBIbUs6OO$Qykc(M=1zfqJ_4Ru9#LVQYKyHu-EfZcoo zSK9u;<$P|0u09|e4|P%c9i6&Xd*FeGH^50Vm^l3sl=fA~Ta)wexi! zr24=!wj?nzc?NwA+TLx1JzB@$YUZNw`dchtmWvD$*#g;#S066*g_?k%93roo)Vd8J z$AuxmHj{v+$X2MVF1&*Vs@dV?pQ~)w$lfh;OdD`5Oh^uFg$3P5T7DOug9)y9La~wa%mn<>nA$aO=Tl za*~1Kq%yQb1$r-_NkzTT-4_k5LM4UgZ0eimO=#DEqcgh{Q`3(JAq-zjzpQjH_!;eF zZUAXO<^=>6;w|Ww zw}4<=vkt$$ZquTUpZ!SG5#xR_C0X#n(^8JJS;IWxWz5h%br`(-%9|73RL=SKiA1f? z+4$|lI-!CB^Ea8SdVf7FDjD&50Ie=9`?SvXH4dk?PG=TX9p#{HZou zq%==270X~@=2<@%ndK7+nP>M+Ecw}hy-5ZU!TmPhUL}AES6eQ|G8dnFh3t_XzC+8q zlj(CX%i=a@VZ5g15p}6)(Q@+o#dNE&Q`d^?0gJWVoz=GesN2zCS@zKfpI8-GS8xk; z==i15#)^h@7$#PhXViRX&(vv8iOd)nkt+t?o9CTg4}mgG5-A%0(Vjwn;xi|UQU znbGJ9c!=r|`Bf(rsS+0}*vnwtsJtBUJvc|$E&JHaOpj>Pb(#xPW86I6JIWqePc6$T zCUO1Jc2s55;4)pnFCFwbSbmI8m>Oz!f7stPXw#euln#p9X57j&&n(COz$qFCO$P;} zl9-M`aU!D|TnslJW9kMhRQ=w)gq7dxm}ZT4l$cNBzRXR~|y&6{t~(&twE| zU5oCH1b2=D-{z#=>yXPwWKjw^vE4gsHX5tOgXnnFxVr0sft1YoE_zFwCG68m|B?-e zAME;*c{rbTsG#Npf0guu?%F7o5mC~Wt5}=f&1#RaDml{F?ue2_5_fcE2^NG9tB{}R zjaN0$+5s*G7i|zhC8LW0HRr~F`lWo2fr^toD#tAeCT6)MdndBGF%P|K1}!@JP6#O= zP<~1oU+a&h$llnLlVrm0wd#5YIVZjFj21Qz=xLFk6{$vPYOrzzc7fdAQz{W4$irDZ zuuO=U2Y$ZM?}2%TFKAdNThoYga@2F_oHfi9VT;nnlfZ?Gb2DjU{K^#Scq@^<|0Y50 zQDmv9FU36Q)QT9!#Lfw+KhQHW^k|4J(H8edF=@63X69@LIY_q?g&v}av%|&3(Q}5I z@ocmz?|#GAEI~}ei_5$^v6~G=(cT!ah=8tnyVpi-;R)P9`7{SK1C9qnP&}Mz&xV^1 zY^jtR5rpKmhgr7oL`uKxbaMPzo-IAQfibaviLQ#je9aEciOe1@9#ujaddTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); - exTabHolder->addTab(new QWidget(),tr("Trade Mastercoin/Smart Properties")); + exTabHolder->addTab(metaDExTab,tr("Trade Mastercoin/Smart Properties")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index b35d15c908cef..dbf2f14cb1128 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -14,6 +14,7 @@ class ReceiveCoinsDialog; class SendCoinsDialog; class SendMPDialog; class LookupSPDialog; +class MetaDExDialog; class SendCoinsRecipient; class TransactionView; class BalancesView; @@ -69,7 +70,7 @@ class WalletView : public QStackedWidget SendCoinsDialog *sendCoinsTab; SendMPDialog *sendMPTab; LookupSPDialog *spLookupTab; - + MetaDExDialog *metaDExTab; TransactionView *transactionView; BalancesView *balancesView; From 1fe45ef72c5caee8ff5fc3ab0eef2c851d5f5c25 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 20:12:31 -0700 Subject: [PATCH 008/141] More MetaDEx UI stuff --- src/mastercore.cpp | 3 +- src/mastercore.h | 3 +- src/qt/forms/metadexdialog.ui | 80 +++++++++++++------------------ src/qt/metadexdialog.cpp | 90 ++++++++++++++++++++++++----------- 4 files changed, 97 insertions(+), 79 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 947fd6e296609..b5f8195b29468 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -82,8 +82,7 @@ static const int nBlockTop = 0; static int nWaterlineBlock = 0; // -uint64_t global_MSC_total = 0; -uint64_t global_MSC_RESERVED_total = 0; +uint64_t global_metadex_market; uint64_t global_balance_money_maineco[100000]; uint64_t global_balance_reserved_maineco[100000]; uint64_t global_balance_money_testeco[100000]; diff --git a/src/mastercore.h b/src/mastercore.h index 59d4cfcd6ac1a..3b0de19392c0a 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -340,10 +340,9 @@ class CMPPending } }; -extern uint64_t global_MSC_total; -extern uint64_t global_MSC_RESERVED_total; //temp - only supporting 100,000 properties per eco here, research best way to expand array //these 4 arrays use about 3MB total memory with 100K properties limit (100000*8*4 bytes) +extern uint64_t global_metadex_market; extern uint64_t global_balance_money_maineco[100000]; extern uint64_t global_balance_reserved_maineco[100000]; extern uint64_t global_balance_money_testeco[100000]; diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index dacae9eafad82..a2bc88e3549a0 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -87,7 +87,7 @@ - + 0 @@ -97,7 +97,7 @@ - + Switch @@ -217,7 +217,7 @@ - + 0 @@ -251,6 +251,9 @@ + + + @@ -258,9 +261,6 @@ - - - @@ -311,6 +311,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -327,26 +340,6 @@ - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -432,7 +425,7 @@ - + 0 @@ -526,6 +519,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -542,26 +548,6 @@ - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 61e6400bc70be..93c3be782c3df 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -67,34 +67,27 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->setupUi(this); this->model = model; -//dummy data -//ui->buyList->addItem('TEST'); -//ui->buyList->addItem('12345678901234567890'); -//ui->buyList->addItem('1234567890 1234567890 1234567890 1234567890 '); -//ui->buyList->addItem('ABCDEFGHIJ'); -//ui->buyList->addItem('ABCDEFGHIJ IKLMNOPQRS TVUWXKR333'); -//ui->buyList->addItem('TEST'); - - -ui->buyList->setColumnCount(3); -for(int i=0; i<5; ++i) { - string strprice = "349.00000006"; - string strtotal = "123456.00000001"; - string strmsctotal = "123456.00000001"; -// QListWidgetItem *item=new QListWidgetItem(QIcon(":/images/Icon.png"),QString::fromStdString(strt)); -// ui->buyList->addItem(item); -QString pstr = QString::fromStdString(strprice); -QString tstr = QString::fromStdString(strtotal); -QString mstr = QString::fromStdString(strmsctotal); - - if (!ui->buyList) { printf("metadex dialog error\n"); return; } - - const int currentRow = ui->buyList->rowCount(); - ui->buyList->setRowCount(currentRow + 1); - ui->buyList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); - ui->buyList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); - ui->buyList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); + //open + global_metadex_market = 3; + //prep lists + ui->buyList->setColumnCount(3); + //dummy data + for(int i=0; i<5; ++i) + { + string strprice = "349.00000006"; + string strtotal = "123456.00000001"; + string strmsctotal = "123456.00000001"; + QString pstr = QString::fromStdString(strprice); + QString tstr = QString::fromStdString(strtotal); + QString mstr = QString::fromStdString(strmsctotal); + if (!ui->buyList) { printf("metadex dialog error\n"); return; } + const int currentRow = ui->buyList->rowCount(); + ui->buyList->setRowCount(currentRow + 1); + ui->buyList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); + ui->buyList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); + ui->buyList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); + } ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); @@ -102,4 +95,45 @@ QString mstr = QString::fromStdString(strmsctotal); ui->buyList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); ui->buyList->setShowGrid(false); ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); -}} + + + + // populate from address selector + unsigned int propertyId = global_metadex_market; + LOCK(cs_tally); + // sell addresses + for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) + { + string address = (my_it->first).c_str(); + unsigned int id; + bool includeAddress=false; + (my_it->second).init(); + while (0 != (id = (my_it->second).next())) + { + if(id==propertyId) { includeAddress=true; break; } + } + if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId + if (!IsMyAddress(address)) continue; //ignore this address, it's not ours + ui->sellAddressCombo->addItem((my_it->first).c_str()); + } + // buy addresses + for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) + { + string address = (my_it->first).c_str(); + bool testeco = false; + if (propertyId > TEST_ECO_PROPERTY_1) testeco = true; + unsigned int id; + bool includeAddress=false; + (my_it->second).init(); + while (0 != (id = (my_it->second).next())) + { + if((id==MASTERCOIN_CURRENCY_MSC) && (!testeco)) { includeAddress=true; break; } + if((id==MASTERCOIN_CURRENCY_TMSC) && (testeco)) { includeAddress=true; break; } + } + if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId + if (!IsMyAddress(address)) continue; //ignore this address, it's not ours + ui->buyAddressCombo->addItem((my_it->first).c_str()); + } + + +} From 7456554d33b74066253e906b6fb4104b4925d41d Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 21:10:01 -0700 Subject: [PATCH 009/141] Initial form updates init --- src/qt/forms/metadexdialog.ui | 6 ++-- src/qt/metadexdialog.cpp | 61 ++++++++++++++++++++++++++++++++--- src/qt/metadexdialog.h | 3 ++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index a2bc88e3549a0..cb8faf911debc 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -36,7 +36,7 @@ 0 - + 75 @@ -168,7 +168,7 @@ - + 75 @@ -378,7 +378,7 @@ - + 75 diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 93c3be782c3df..f24197b89baf9 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -96,11 +96,62 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->setShowGrid(false); ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); - + connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); + FullRefresh(); + +} + +void MetaDExDialog::SwitchMarket() +{ + uint64_t searchPropertyId = 0; + // first let's check if we have a searchText, if not do nothing + string searchText = ui->switchLineEdit->text().toStdString(); + if (searchText.empty()) return; + + // try seeing if we have a numerical search string, if so treat it as a property ID search + try + { + searchPropertyId = boost::lexical_cast(searchText); + } + catch(const boost::bad_lexical_cast &e) { return; } // bad cast to number + + if ((searchPropertyId > 0) && (searchPropertyId < 4294967290)) // sanity check + { + // check if property exists + bool spExists = _my_sps->hasSP(searchPropertyId); + if (!spExists) + { + return; + } + else + { + global_metadex_market = searchPropertyId; + FullRefresh(); + } + } +} + +void MetaDExDialog::FullRefresh() +{ // populate from address selector unsigned int propertyId = global_metadex_market; + bool testeco = false; + if (propertyId > TEST_ECO_PROPERTY_1) testeco = true; LOCK(cs_tally); + + // update form labels + if (testeco) + { + ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/TMSC"); + } + else + { + ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/MSC"); + } + ui->buyMarketLabel->setText("BUY SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); + ui->sellMarketLabel->setText("SELL SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); + // sell addresses for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) { @@ -120,8 +171,6 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) { string address = (my_it->first).c_str(); - bool testeco = false; - if (propertyId > TEST_ECO_PROPERTY_1) testeco = true; unsigned int id; bool includeAddress=false; (my_it->second).init(); @@ -134,6 +183,10 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : if (!IsMyAddress(address)) continue; //ignore this address, it's not ours ui->buyAddressCombo->addItem((my_it->first).c_str()); } +} - +void MetaDExDialog::switchButtonClicked() +{ + SwitchMarket(); } + diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index f3bcc42235c73..4c5c74abd4c3f 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -26,6 +26,8 @@ class MetaDExDialog : public QDialog Q_OBJECT public: + void FullRefresh(); + void SwitchMarket(); explicit MetaDExDialog(QWidget *parent = 0); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ @@ -33,6 +35,7 @@ class MetaDExDialog : public QDialog public slots: + void switchButtonClicked(); private: Ui::MetaDExDialog *ui; From 822176f13d7afcf132b341c51eb06c4579158c34 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 13 Oct 2014 21:52:52 -0700 Subject: [PATCH 010/141] Further stuff for MetaDEx UI --- src/qt/forms/metadexdialog.ui | 4 +- src/qt/metadexdialog.cpp | 82 ++++++++++++++++++++++++++++++++++- src/qt/metadexdialog.h | 4 ++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index cb8faf911debc..59235a9a2b02a 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -196,7 +196,7 @@ - + Your Balance 0.000000000 MSC @@ -404,7 +404,7 @@ - + Your Balance 0.000000000 SPT diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index f24197b89baf9..4e15c37002190 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -97,6 +97,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); + connect(ui->sellAddressCombo, SIGNAL(activated(int)), this, SLOT(sellAddressComboBoxChanged(int))); + connect(ui->buyAddressCombo, SIGNAL(activated(int)), this, SLOT(buyAddressComboBoxChanged(int))); FullRefresh(); @@ -118,10 +120,17 @@ void MetaDExDialog::SwitchMarket() if ((searchPropertyId > 0) && (searchPropertyId < 4294967290)) // sanity check { + // check if trying to trade against self + if ((searchPropertyId == 1) || (searchPropertyId == 2)) + { + //todo add property cannot be traded against self messgevox + return; + } // check if property exists bool spExists = _my_sps->hasSP(searchPropertyId); if (!spExists) { + //todo add property not found messagebox return; } else @@ -132,14 +141,65 @@ void MetaDExDialog::SwitchMarket() } } +void MetaDExDialog::UpdateSellAddress() +{ + unsigned int propertyId = global_metadex_market; + bool divisible = isPropertyDivisible(propertyId); + QString currentSetSellAddress = ui->sellAddressCombo->currentText(); + int64_t balanceAvailable = getUserAvailableMPbalance(currentSetSellAddress.toStdString(), propertyId); + string labStr; + if (divisible) + { + labStr = "Your balance: " + FormatDivisibleMP(balanceAvailable) + " SPT"; + } + else + { + labStr = "Your balance: " + FormatIndivisibleMP(balanceAvailable) + " SPT"; + } + QString qLabStr = QString::fromStdString(labStr); + ui->yourSellBalanceLabel->setText(qLabStr); +} + +void MetaDExDialog::UpdateBuyAddress() +{ + unsigned int propertyId = global_metadex_market; + bool testeco = false; + if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; + QString currentSetBuyAddress = ui->buyAddressCombo->currentText(); + int64_t balanceAvailable; + string tokenStr; + if (testeco) + { + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_CURRENCY_TMSC); + tokenStr = " TMSC"; + } + else + { + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_CURRENCY_MSC); + tokenStr = " MSC"; + + } + string labStr = "Your balance: " + FormatDivisibleMP(balanceAvailable) + tokenStr; + QString qLabStr = QString::fromStdString(labStr); + ui->yourBuyBalanceLabel->setText(qLabStr); +} + void MetaDExDialog::FullRefresh() { // populate from address selector unsigned int propertyId = global_metadex_market; bool testeco = false; - if (propertyId > TEST_ECO_PROPERTY_1) testeco = true; + if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; LOCK(cs_tally); + // get currently selected addresses + QString currentSetBuyAddress = ui->buyAddressCombo->currentText(); + QString currentSetSellAddress = ui->sellAddressCombo->currentText(); + + // clear address selectors + ui->buyAddressCombo->clear(); + ui->sellAddressCombo->clear(); + // update form labels if (testeco) { @@ -183,6 +243,26 @@ void MetaDExDialog::FullRefresh() if (!IsMyAddress(address)) continue; //ignore this address, it's not ours ui->buyAddressCombo->addItem((my_it->first).c_str()); } + + // attempt to set buy and sell addresses back to values before refresh + int sellIdx = ui->sellAddressCombo->findText(currentSetSellAddress); + if (sellIdx != -1) { ui->sellAddressCombo->setCurrentIndex(sellIdx); } // -1 means the new prop doesn't have the previously selected address + int buyIdx = ui->buyAddressCombo->findText(currentSetBuyAddress); + if (buyIdx != -1) { ui->buyAddressCombo->setCurrentIndex(buyIdx); } // -1 means the new prop doesn't have the previously selected address + + // update the balances + UpdateSellAddress(); + UpdateBuyAddress(); +} + +void MetaDExDialog::buyAddressComboBoxChanged(int idx) +{ + UpdateBuyAddress(); +} + +void MetaDExDialog::sellAddressComboBoxChanged(int idx) +{ + UpdateSellAddress(); } void MetaDExDialog::switchButtonClicked() diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index 4c5c74abd4c3f..ff651874ba980 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -28,6 +28,8 @@ class MetaDExDialog : public QDialog public: void FullRefresh(); void SwitchMarket(); + void UpdateSellAddress(); + void UpdateBuyAddress(); explicit MetaDExDialog(QWidget *parent = 0); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ @@ -36,6 +38,8 @@ class MetaDExDialog : public QDialog public slots: void switchButtonClicked(); + void sellAddressComboBoxChanged(int idx); + void buyAddressComboBoxChanged(int idx); private: Ui::MetaDExDialog *ui; From be375934646b0f269ff4fa8990abdd1c11c1b2dd Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 14 Oct 2014 15:00:25 -0700 Subject: [PATCH 011/141] More MetaDEX UI stuff --- src/qt/forms/metadexdialog.ui | 149 ++++++++++++++++++++++++---------- src/qt/metadexdialog.cpp | 65 +++++++++++++++ 2 files changed, 169 insertions(+), 45 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 59235a9a2b02a..cfa3e4c826ffb 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -116,36 +116,102 @@ 10 + + + + + + 6 + + + 0 + - - - - 75 - true - - - - - - - Your Open Positions - - - - - - - - 0 - 0 - + + + QFrame::StyledPanel - - - 0 - 1 - + + QFrame::Raised + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + + + 0 + + + 0 + + + + + + 75 + true + + + + + + + Your Open Positions + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 80 + + + + 0 + + + 100 + + + + + + + + @@ -244,7 +310,7 @@ - Amount (SP#3): + Amount (SPT): @@ -257,7 +323,7 @@ - Price Per SP#3: + Price Per SPT: @@ -289,7 +355,7 @@ - MSC + TMSC @@ -325,7 +391,7 @@ - + 75 @@ -341,7 +407,7 @@ - + Buy SP#3 @@ -452,7 +518,7 @@ - Amount (SP#3): + Amount (SPT): @@ -462,7 +528,7 @@ - Price Per SP#3: + Price Per SPT: @@ -497,7 +563,7 @@ - MSC + TMSC @@ -533,7 +599,7 @@ - + 75 @@ -549,7 +615,7 @@ - + Sell SP#3 @@ -558,14 +624,7 @@ - - - - 0 - 0 - - - + diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 4e15c37002190..c5b674d5777cb 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -72,6 +72,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : //prep lists ui->buyList->setColumnCount(3); + ui->sellList->setColumnCount(3); + ui->openOrders->setColumnCount(5); //dummy data for(int i=0; i<5; ++i) { @@ -87,7 +89,36 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); ui->buyList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); ui->buyList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); + ui->sellList->setRowCount(currentRow + 1); + ui->sellList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); + ui->sellList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); + ui->sellList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); } + //dummy orders + const int currentRow = ui->openOrders->rowCount(); + ui->openOrders->setRowCount(currentRow + 1); + ui->openOrders->setItem(currentRow, 0, new QTableWidgetItem("1FakeBitcoinAddressDoNotSend")); + ui->openOrders->setItem(currentRow, 1, new QTableWidgetItem("Sell")); + ui->openOrders->setItem(currentRow, 2, new QTableWidgetItem("0.00004565")); + ui->openOrders->setItem(currentRow, 3, new QTableWidgetItem("345.45643222")); + ui->openOrders->setItem(currentRow, 4, new QTableWidgetItem("0.015770081")); + + ui->openOrders->setHorizontalHeaderItem(0, new QTableWidgetItem("Address")); + ui->openOrders->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); + ui->openOrders->setHorizontalHeaderItem(2, new QTableWidgetItem("Unit Price")); + ui->openOrders->verticalHeader()->setVisible(false); + #if QT_VERSION < 0x050000 + ui->openOrders->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + #else + ui->openOrders->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + #endif + ui->openOrders->horizontalHeader()->resizeSection(1, 60); + ui->openOrders->horizontalHeader()->resizeSection(2, 140); + ui->openOrders->horizontalHeader()->resizeSection(3, 140); + ui->openOrders->horizontalHeader()->resizeSection(4, 140); + ui->openOrders->setShowGrid(false); + ui->openOrders->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); @@ -96,6 +127,14 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->setShowGrid(false); ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->sellList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); + ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); + ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); + ui->sellList->verticalHeader()->setVisible(false); + ui->sellList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + ui->sellList->setShowGrid(false); + ui->sellList->setSelectionBehavior(QAbstractItemView::SelectRows); + connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); connect(ui->sellAddressCombo, SIGNAL(activated(int)), this, SLOT(sellAddressComboBoxChanged(int))); connect(ui->buyAddressCombo, SIGNAL(activated(int)), this, SLOT(buyAddressComboBoxChanged(int))); @@ -204,13 +243,30 @@ void MetaDExDialog::FullRefresh() if (testeco) { ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/TMSC"); + ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("TMSC")); + ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("TMSC")); + ui->buyTotalLabel->setText("0.00000000 TMSC"); + ui->sellTotalLabel->setText("0.00000000 TMSC"); + ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); + ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("TMSC")); } else { ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/MSC"); + ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("MSC")); + ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("MSC")); + ui->buyTotalLabel->setText("0.00000000 MSC"); + ui->sellTotalLabel->setText("0.00000000 MSC"); + ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); + ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("MSC")); } + ui->buyMarketLabel->setText("BUY SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); ui->sellMarketLabel->setText("SELL SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); + ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); + ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); + ui->sellButton->setText("Sell SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); + ui->buyButton->setText("Buy SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); // sell addresses for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) @@ -253,6 +309,15 @@ void MetaDExDialog::FullRefresh() // update the balances UpdateSellAddress(); UpdateBuyAddress(); + + // silly sizing + QRect rect = ui->openOrders->geometry(); + int tableHeight = 2 + ui->openOrders->horizontalHeader()->height(); + for(int i = 0; i < ui->openOrders->rowCount(); i++){ + tableHeight += ui->openOrders->rowHeight(i); + } + rect.setHeight(tableHeight); + ui->openOrders->setGeometry(rect); } void MetaDExDialog::buyAddressComboBoxChanged(int idx) From 9b8fb1c38953bc5709a1bf8f74344b8da33e92cf Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 16 Oct 2014 15:48:19 -0700 Subject: [PATCH 012/141] Various fixes from 0.0.8 + More MetaDEx --- src/qt/balancesview.cpp | 92 ++++++++++++++++++++++------------- src/qt/balancesview.h | 4 +- src/qt/forms/metadexdialog.ui | 4 +- src/qt/metadexdialog.cpp | 4 ++ src/qt/sendmpdialog.cpp | 46 +++++++++++------- src/qt/sendmpdialog.h | 1 + src/qt/splashscreen.cpp | 2 +- src/qt/walletview.cpp | 1 + 8 files changed, 99 insertions(+), 55 deletions(-) diff --git a/src/qt/balancesview.cpp b/src/qt/balancesview.cpp index 1899c519f1e21..e0e253968b59c 100644 --- a/src/qt/balancesview.cpp +++ b/src/qt/balancesview.cpp @@ -104,38 +104,6 @@ BalancesView::BalancesView(QWidget *parent) : #else propSelectorWidget->setFixedWidth(300); #endif - propSelectorWidget->addItem("Wallet Totals (Summary)","2147483646"); //use last possible ID for summary for now - // trigger update of global balances - set_wallet_totals(); - // populate property selector - for (unsigned int propertyId = 1; propertyId<100000; propertyId++) - { - if ((global_balance_money_maineco[propertyId] > 0) || (global_balance_reserved_maineco[propertyId] > 0)) - { - string spName; - spName = getPropertyName(propertyId).c_str(); - if(spName.size()>20) spName=spName.substr(0,20)+"..."; - string spId = static_cast( &(ostringstream() << propertyId) )->str(); - spName += " (#" + spId + ")"; - propSelectorWidget->addItem(spName.c_str(),spId.c_str()); -//propSelectorWidget->addItem(tr(spName.c_str())); - } - } - for (unsigned int propertyId = 1; propertyId<100000; propertyId++) - { - if ((global_balance_money_testeco[propertyId] > 0) || (global_balance_reserved_testeco[propertyId] > 0)) - { - string spName; - spName = getPropertyName(propertyId+2147483647).c_str(); - if(spName.size()>20) spName=spName.substr(0,20)+"..."; - string spId = static_cast( &(ostringstream() << propertyId+2147483647) )->str(); - spName += " (#" + spId + ")"; - propSelectorWidget->addItem(spName.c_str(),spId.c_str()); - - // spName += " (#" + static_cast( &(ostringstream() << propertyId+2147483647) )->str() + ")"; - // propSelectorWidget->addItem(tr(spName.c_str())); - } - } //add the selector to the layout hlayout->addWidget(propSelectorWidget); @@ -205,11 +173,63 @@ BalancesView::BalancesView(QWidget *parent) : connect(balancesCopyAddressAction, SIGNAL(triggered()), this, SLOT(balancesCopyAddress())); connect(balancesCopyLabelAction, SIGNAL(triggered()), this, SLOT(balancesCopyLabel())); connect(balancesCopyAmountAction, SIGNAL(triggered()), this, SLOT(balancesCopyAmount())); + UpdatePropSelector(); +} + +void BalancesView::UpdatePropSelector() +{ + //printf("balancesview::propselectorupdatecalled\n"); + QString spId = propSelectorWidget->itemData(propSelectorWidget->currentIndex()).toString(); + propSelectorWidget->clear(); + propSelectorWidget->addItem("Wallet Totals (Summary)","2147483646"); //use last possible ID for summary for now + // trigger update of global balances + set_wallet_totals(); + // populate property selector + for (unsigned int propertyId = 1; propertyId<100000; propertyId++) + { + if ((global_balance_money_maineco[propertyId] > 0) || (global_balance_reserved_maineco[propertyId] > 0)) + { + string spName; + spName = getPropertyName(propertyId).c_str(); + if(spName.size()>20) spName=spName.substr(0,20)+"..."; + string spId = static_cast( &(ostringstream() << propertyId) )->str(); + spName += " (#" + spId + ")"; + propSelectorWidget->addItem(spName.c_str(),spId.c_str()); + } + } + for (unsigned int propertyId = 1; propertyId<100000; propertyId++) + { + if ((global_balance_money_testeco[propertyId] > 0) || (global_balance_reserved_testeco[propertyId] > 0)) + { + string spName; + spName = getPropertyName(propertyId+2147483647).c_str(); + if(spName.size()>20) spName=spName.substr(0,20)+"..."; + string spId = static_cast( &(ostringstream() << propertyId+2147483647) )->str(); + spName += " (#" + spId + ")"; + propSelectorWidget->addItem(spName.c_str(),spId.c_str()); + } + } + int propIdx = propSelectorWidget->findData(spId); + if (propIdx != -1) { propSelectorWidget->setCurrentIndex(propIdx); } +} + +void BalancesView::setModel(WalletModel *model) +{ + this->model = model; + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); +} + +void BalancesView::UpdateBalances() +{ + //printf("balancesview::updatebalances()\n"); + propSelectorChanged(0); + UpdatePropSelector(); } void BalancesView::propSelectorChanged(int idx) { - QString spId = propSelectorWidget->itemData(idx).toString(); + //printf("balancesview::propselectorchanged()\n"); + QString spId = propSelectorWidget->itemData(propSelectorWidget->currentIndex()).toString(); unsigned int propertyId = spId.toUInt(); //repopulate with new selected balances //prep matrix @@ -257,3 +277,9 @@ void BalancesView::resizeEvent(QResizeEvent* event) // QWidget::resizeEvent(event); // columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress); } + +void BalancesView::balancesUpdated() +{ + UpdateBalances(); +} + diff --git a/src/qt/balancesview.h b/src/qt/balancesview.h index cdd57d290a989..a83d3ec996c93 100644 --- a/src/qt/balancesview.h +++ b/src/qt/balancesview.h @@ -34,7 +34,8 @@ class BalancesView : public QWidget explicit BalancesView(QWidget *parent = 0); void setModel(WalletModel *model); - + void UpdateBalances(); + void UpdatePropSelector(); // Date ranges for filter enum DateEnum { @@ -102,6 +103,7 @@ public slots: void balancesCopyAddress(); void balancesCopyLabel(); void balancesCopyAmount(); + void balancesUpdated(); }; #endif // BALANCESVIEW_H diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index cfa3e4c826ffb..1b6b706ff75cb 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -353,7 +353,7 @@ - + TMSC @@ -561,7 +561,7 @@ - + TMSC diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index c5b674d5777cb..664af4d7300aa 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -249,6 +249,8 @@ void MetaDExDialog::FullRefresh() ui->sellTotalLabel->setText("0.00000000 TMSC"); ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("TMSC")); + ui->sellTM->setText("TMSC"); + ui->buyTM->setText("TMSC"); } else { @@ -259,6 +261,8 @@ void MetaDExDialog::FullRefresh() ui->sellTotalLabel->setText("0.00000000 MSC"); ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("MSC")); + ui->sellTM->setText("MSC"); + ui->buyTM->setText("MSC"); } ui->buyMarketLabel->setText("BUY SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index 73650d7c70de4..55217dd409a13 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -70,7 +70,7 @@ SendMPDialog::SendMPDialog(QWidget *parent) : model(0) { ui->setupUi(this); - this->model = model; +// this->model = model; #ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac ui->clearButton->setIcon(QIcon()); @@ -81,7 +81,29 @@ SendMPDialog::SendMPDialog(QWidget *parent) : ui->sendToLineEdit->setPlaceholderText("Enter a Master Protocol address (e.g. 1MaSTeRPRotocolADDreSShef77z6A5S4P)"); ui->amountLineEdit->setPlaceholderText("Enter Amount"); - // populate property selector + // connect actions + connect(ui->propertyComboBox, SIGNAL(activated(int)), this, SLOT(propertyComboBoxChanged(int))); + connect(ui->sendFromComboBox, SIGNAL(activated(int)), this, SLOT(sendFromComboBoxChanged(int))); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clearButtonClicked())); + connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendButtonClicked())); + + // initial update + updatePropSelector(); + updateProperty(); + updateFrom(); +} + +void SendMPDialog::setModel(WalletModel *model) +{ + this->model = model; + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); +} + +void SendMPDialog::updatePropSelector() +{ + //printf("sendmpdialog::updatePropSelector()\n"); + QString spId = ui->propertyComboBox->itemData(ui->propertyComboBox->currentIndex()).toString(); + ui->propertyComboBox->clear(); for (unsigned int propertyId = 1; propertyId<100000; propertyId++) { if ((global_balance_money_maineco[propertyId] > 0) || (global_balance_reserved_maineco[propertyId] > 0)) @@ -108,22 +130,8 @@ SendMPDialog::SendMPDialog(QWidget *parent) : ui->propertyComboBox->addItem(spName.c_str(),spId.c_str()); } } - - // connect actions - connect(ui->propertyComboBox, SIGNAL(activated(int)), this, SLOT(propertyComboBoxChanged(int))); - connect(ui->sendFromComboBox, SIGNAL(activated(int)), this, SLOT(sendFromComboBoxChanged(int))); - connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clearButtonClicked())); - connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendButtonClicked())); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); - - // initial update - updateProperty(); - updateFrom(); -} - -void SendMPDialog::setModel(WalletModel *model) -{ - this->model = model; + int propIdx = ui->propertyComboBox->findData(spId); + if (propIdx != -1) { ui->propertyComboBox->setCurrentIndex(propIdx); } } void SendMPDialog::clearFields() @@ -180,6 +188,7 @@ void SendMPDialog::updateProperty() } if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId if (!IsMyAddress(address)) continue; //ignore this address, it's not ours + if ((address.substr(0,1)=="2") || (address.substr(0,3)=="3")) continue; //quick hack to not show P2SH addresses in from selector (can't be sent from UI) ui->sendFromComboBox->addItem((my_it->first).c_str()); } @@ -443,5 +452,6 @@ void SendMPDialog::sendButtonClicked() void SendMPDialog::balancesUpdated() { + updatePropSelector(); updateBalances(); } diff --git a/src/qt/sendmpdialog.h b/src/qt/sendmpdialog.h index fb07004241a9e..948bcae66e330 100644 --- a/src/qt/sendmpdialog.h +++ b/src/qt/sendmpdialog.h @@ -36,6 +36,7 @@ class SendMPDialog : public QDialog void updateFrom(); void updateProperty(); void updateBalances(); + void updatePropSelector(); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ QWidget *setupTabChain(QWidget *prev); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 0c0e689153398..95a4488614c2b 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -31,7 +31,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest // define text to place QString titleText = tr("Master Core"); - QString versionText = QString("Experimental UI Alpha 0.0002"); //QString("Version %1").arg(QString::fromStdString(FormatFullVersion())); + QString versionText = QString("Experimental UI Alpha 0.0002b"); //QString("Version %1").arg(QString::fromStdString(FormatFullVersion())); QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); QString copyrightMSC = QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index bd1e6774a7443..14c80b347920f 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -177,6 +177,7 @@ void WalletView::setWalletModel(WalletModel *walletModel) receiveCoinsPage->setModel(walletModel); sendCoinsTab->setModel(walletModel); sendMPTab->setModel(walletModel); + balancesView->setModel(walletModel); if (walletModel) { From 270e6d7ae4b17eb07db0d6d4a56e43b0d4ef5ce6 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 16 Oct 2014 16:38:34 -0700 Subject: [PATCH 013/141] strToInt64 fix and more metadex --- src/mastercore.cpp | 2 +- src/qt/forms/metadexdialog.ui | 8 ++++---- src/qt/metadexdialog.cpp | 32 ++++++++++++++++++++++++++++++++ src/qt/metadexdialog.h | 5 +++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index ac04f61738fb0..aebbe2ef5fec1 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -336,7 +336,7 @@ int64_t mastercore::strToInt64(std::string strAmount, bool divisible) { size_t posSecond = strAmount.find(".", pos+1); //check for existence of second decimal point, if so invalidate amount if (posSecond!=std::string::npos) return 0; - if ((strAmount.size()-pos)<8) + if ((strAmount.size()-pos)<9) { //there are decimals either exact or not enough, pad as needed string strRightOfDecimal = strAmount.substr(pos+1); unsigned int zerosToPad = 8-strRightOfDecimal.size(); diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 1b6b706ff75cb..07ed90fa4304c 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -315,10 +315,10 @@ - + - + @@ -523,7 +523,7 @@ - + @@ -533,7 +533,7 @@ - + diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 664af4d7300aa..b869977ad85a1 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -138,6 +138,10 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); connect(ui->sellAddressCombo, SIGNAL(activated(int)), this, SLOT(sellAddressComboBoxChanged(int))); connect(ui->buyAddressCombo, SIGNAL(activated(int)), this, SLOT(buyAddressComboBoxChanged(int))); + connect(ui->sellAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); + connect(ui->sellPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); + connect(ui->buyAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); + connect(ui->buyPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); FullRefresh(); @@ -339,3 +343,31 @@ void MetaDExDialog::switchButtonClicked() SwitchMarket(); } +void MetaDExDialog::buyRecalc() +{ + unsigned int propertyId = global_metadex_market; + bool divisible = isPropertyDivisible(propertyId); + bool testeco = false; + if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; + int64_t buyAmount = strToInt64(ui->buyAmountLE->text().toStdString(),divisible); + int64_t buyPrice = strToInt64(ui->buyPriceLE->text().toStdString(),true); +printf("%s\n",FormatDivisibleMP(buyPrice).c_str()); + if ((0>=buyAmount) || (0>=buyPrice)) return; // break out before invalid calc + //could result in overflow TODO + uint64_t totalPrice = buyAmount * buyPrice; + string totalLabel = FormatDivisibleMP(totalPrice); + if (testeco) + { + ui->buyTotalLabel->setText(QString::fromStdString(totalLabel) + " TMSC"); + } + else + { + ui->buyTotalLabel->setText(QString::fromStdString(totalLabel) + " MSC"); + } +} + +void MetaDExDialog::sellRecalc() +{ + +} + diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index ff651874ba980..5f80e776bfd1b 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -45,8 +45,9 @@ public slots: Ui::MetaDExDialog *ui; WalletModel *model; -//private slots: - +private slots: + void buyRecalc(); + void sellRecalc(); signals: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); From 03adf6a7a679a0980e0668d12d67edc7ac0e383a Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 16 Oct 2014 18:38:20 -0700 Subject: [PATCH 014/141] More work on sending trades in metadex UI --- src/qt/metadexdialog.cpp | 267 ++++++++++++++++++++++++++++++++++++++- src/qt/metadexdialog.h | 6 + src/qt/sendmpdialog.cpp | 2 +- src/qt/walletview.cpp | 1 + 4 files changed, 273 insertions(+), 3 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index b869977ad85a1..4fd6c246a7503 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -55,6 +55,7 @@ using namespace leveldb; #include "mastercore_tx.h" #include "mastercore_sp.h" +#include #include #include #include @@ -136,6 +137,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->sellList->setSelectionBehavior(QAbstractItemView::SelectRows); connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); + connect(ui->buyButton, SIGNAL(clicked()), this, SLOT(buyTrade())); + connect(ui->sellButton, SIGNAL(clicked()), this, SLOT(sellTrade())); connect(ui->sellAddressCombo, SIGNAL(activated(int)), this, SLOT(sellAddressComboBoxChanged(int))); connect(ui->buyAddressCombo, SIGNAL(activated(int)), this, SLOT(buyAddressComboBoxChanged(int))); connect(ui->sellAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); @@ -147,6 +150,12 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : } +void MetaDExDialog::setModel(WalletModel *model) +{ + this->model = model; +// connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); +} + void MetaDExDialog::SwitchMarket() { uint64_t searchPropertyId = 0; @@ -343,6 +352,17 @@ void MetaDExDialog::switchButtonClicked() SwitchMarket(); } +void MetaDExDialog::sellTrade() +{ + sendTrade(true); +} + +void MetaDExDialog::buyTrade() +{ + sendTrade(false); +} + + void MetaDExDialog::buyRecalc() { unsigned int propertyId = global_metadex_market; @@ -351,8 +371,7 @@ void MetaDExDialog::buyRecalc() if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; int64_t buyAmount = strToInt64(ui->buyAmountLE->text().toStdString(),divisible); int64_t buyPrice = strToInt64(ui->buyPriceLE->text().toStdString(),true); -printf("%s\n",FormatDivisibleMP(buyPrice).c_str()); - if ((0>=buyAmount) || (0>=buyPrice)) return; // break out before invalid calc + if ((0>=buyAmount) || (0>=buyPrice)) { ui->buyTotalLabel->setText("N/A"); return; } // break out before invalid calc //could result in overflow TODO uint64_t totalPrice = buyAmount * buyPrice; string totalLabel = FormatDivisibleMP(totalPrice); @@ -368,6 +387,250 @@ printf("%s\n",FormatDivisibleMP(buyPrice).c_str()); void MetaDExDialog::sellRecalc() { + unsigned int propertyId = global_metadex_market; + bool divisible = isPropertyDivisible(propertyId); + bool testeco = false; + if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; + int64_t sellAmount = strToInt64(ui->sellAmountLE->text().toStdString(),divisible); + int64_t sellPrice = strToInt64(ui->sellPriceLE->text().toStdString(),true); + if ((0>=sellAmount) || (0>=sellPrice)) { ui->sellTotalLabel->setText("N/A"); return; } // break out before invalid calc + //could result in overflow TODO + uint64_t totalPrice = sellAmount * sellPrice; + string totalLabel = FormatDivisibleMP(totalPrice); + if (testeco) + { + ui->sellTotalLabel->setText(QString::fromStdString(totalLabel) + " TMSC"); + } + else + { + ui->sellTotalLabel->setText(QString::fromStdString(totalLabel) + " MSC"); + } +} + +void MetaDExDialog::sendTrade(bool sell) +{ + unsigned int propertyId = global_metadex_market; + bool divisible = isPropertyDivisible(propertyId); + bool testeco = false; + if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; + + // obtain the selected sender address + string strFromAddress; + if (!sell) { strFromAddress = ui->buyAddressCombo->currentText().toStdString(); } else { strFromAddress = ui->sellAddressCombo->currentText().toStdString(); } + // push recipient address into a CBitcoinAddress type and check validity + CBitcoinAddress fromAddress; + if (false == strFromAddress.empty()) { fromAddress.SetString(strFromAddress); } + if (!fromAddress.IsValid()) + { + QMessageBox::critical( this, "Unable to send MetaDEx transaction", + "The sender address selected is not valid.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); + return; + } + + // warn if we have to truncate the amount due to a decimal amount for an indivisible property, but allow send to continue + string strAmount = ui->buyAmountLE->text().toStdString(); + if (!divisible) + { + size_t pos = strAmount.find("."); + if (pos!=std::string::npos) + { + string tmpStrAmount = strAmount.substr(0,pos); + string strMsgText = "The amount entered contains a decimal however the property being transacted is indivisible.\n\nThe amount entered will be truncated as follows:\n"; + strMsgText += "Original amount entered: " + strAmount + "\nAmount that will be used: " + tmpStrAmount + "\n\n"; + strMsgText += "Do you still wish to proceed with the transaction?"; + QString msgText = QString::fromStdString(strMsgText); + QMessageBox::StandardButton responseClick; + responseClick = QMessageBox::question(this, "Amount truncation warning", msgText, QMessageBox::Yes|QMessageBox::No); + if (responseClick == QMessageBox::No) + { + QMessageBox::critical( this, "MetaDEx transaction cancelled", + "The MetaDEx transaction has been cancelled.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); + return; + } + strAmount = tmpStrAmount; + ui->buyAmountLE->setText(QString::fromStdString(strAmount)); + } + } + + // use strToInt64 function to get the amounts, using divisibility of the property + int64_t amount = 0; + int64_t price = 0; + if (!sell) + { + amount = strToInt64(ui->buyAmountLE->text().toStdString(),divisible); + price = strToInt64(ui->buyPriceLE->text().toStdString(),true); + } + else + { + amount = strToInt64(ui->sellAmountLE->text().toStdString(),divisible); + price = strToInt64(ui->sellPriceLE->text().toStdString(),true); + } + + //could result in overflow TODO + uint64_t totalPrice = amount * price; + if ((0>=amount) || (0>=price) || (0>=totalPrice)) + { + QMessageBox::critical( this, "Unable to send MetaDEx transaction", + "The amount entered is not valid.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); + return; + } + + // check if sending address has enough funds + int64_t balanceAvailable = 0; + if (!sell) + { + if (testeco) + { + balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), MASTERCOIN_CURRENCY_TMSC); + } + else + { + balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), MASTERCOIN_CURRENCY_MSC); + } + } + else + { + balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), propertyId); + } + if (((!sell) && (totalPrice>balanceAvailable)) || ((sell) && (amount>balanceAvailable))) + { + QMessageBox::critical( this, "Unable to send MetaDEx transaction", + "The selected sending address does not have a sufficient balance to cover the amount entered.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); + return; + } + + // check if wallet is still syncing, as this will currently cause a lockup if we try to send - compare our chain to peers to see if we're up to date + // Bitcoin Core devs have removed GetNumBlocksOfPeers, switching to a time based best guess scenario + uint32_t intBlockDate = GetLatestBlockTime(); // uint32, not using time_t for portability + QDateTime currentDate = QDateTime::currentDateTime(); + int secs = QDateTime::fromTime_t(intBlockDate).secsTo(currentDate); + if(secs > 90*60) + { + QMessageBox::critical( this, "Unable to send MetaDEx transaction", + "The client is still synchronizing. Sending transactions can currently be performed only when the client has completed synchronizing." ); + return; + } + + // validation checks all look ok, let's throw up a confirmation dialog + string strMsgText = "You are about to send the following MetaDEx transaction, please check the details thoroughly:\n\n"; + string spNum = static_cast( &(ostringstream() << propertyId) )->str(); + string propDetails = "#" + spNum; + string buyStr; + string sellStr; + strMsgText += "Type: Trade Request\nFrom: " + fromAddress.ToString() + "\n\n"; + if (!sell) // clicked buy + { + if (divisible) { buyStr = FormatDivisibleMP(amount); } else { buyStr = FormatIndivisibleMP(amount); } + buyStr += " SPT " + propDetails + ""; + sellStr = FormatDivisibleMP(totalPrice); + if (testeco) { sellStr += " TMSC #2"; } else { sellStr += " MSC #1"; } + strMsgText += "Buying: " + buyStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; + if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } + strMsgText += "\nTotal: " + sellStr; + } + else // clicked sell + { + buyStr = FormatDivisibleMP(totalPrice); + if (divisible) { sellStr = FormatDivisibleMP(amount); } else { sellStr = FormatIndivisibleMP(amount); } + if (testeco) { buyStr += " TMSC #2"; } else { buyStr += " MSC #1"; } + sellStr += " SPT " + propDetails + ""; + strMsgText += "Selling: " + sellStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; + if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } + strMsgText += "\nTotal: " + buyStr; + } + strMsgText += "\n\nAre you sure you wish to send this transaction?"; + QString msgText = QString::fromStdString(strMsgText); + QMessageBox::StandardButton responseClick; + responseClick = QMessageBox::question(this, "Confirm MetaDEx transaction", msgText, QMessageBox::Yes|QMessageBox::No); + if (responseClick == QMessageBox::No) + { + QMessageBox::critical( this, "MetaDEx transaction cancelled", + "The transaction has been cancelled.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); + return; + } + + // unlock the wallet + WalletModel::UnlockContext ctx(model->requestUnlock()); + if(!ctx.isValid()) + { + // Unlock wallet was cancelled/failed + QMessageBox::critical( this, "MetaDEx transaction failed", + "The transaction has been cancelled.\n\nThe wallet unlock process must be completed to send a transaction." ); + return; + } +/* + // send the transaction - UI will not send any extra reference amounts at this stage + int code = 0; + uint256 sendTXID = send_INTERNAL_1packet(fromAddress.ToString(), refAddress.ToString(), fromAddress.ToString(), propertyId, sendAmount, 0, 0, MSC_TYPE_SIMPLE_SEND, 0, &code); + if (0 != code) + { + string strCode = boost::lexical_cast(code); + string strError; + switch(code) + { + case -212: + strError = "Error choosing inputs for the send transaction"; + break; + case -233: + strError = "Error with redemption address"; + break; + case -220: + strError = "Error with redemption address key ID"; + break; + case -221: + strError = "Error obtaining public key for redemption address"; + break; + case -222: + strError = "Error public key for redemption address is not valid"; + break; + case -223: + strError = "Error validating redemption address"; + break; + case -205: + strError = "Error with wallet object"; + break; + case -206: + strError = "Error with selected inputs for the send transaction"; + break; + case -211: + strError = "Error creating transaction (wallet may be locked or fees may not be sufficient)"; + break; + case -213: + strError = "Error committing transaction"; + break; + } + if (strError.empty()) strError = "Error code does not have associated error text."; + QMessageBox::critical( this, "Send transaction failed", + "The send transaction has failed.\n\nThe error code was: " + QString::fromStdString(strCode) + "\nThe error message was:\n" + QString::fromStdString(strError)); + return; + } + else + { + // call an update of the balances + set_wallet_totals(); + updateBalances(); + + // display the result + string strSentText = "Your Master Protocol transaction has been sent.\n\nThe transaction ID is:\n\n"; + strSentText += sendTXID.GetHex() + "\n\n"; + QString sentText = QString::fromStdString(strSentText); + QMessageBox sentDialog; + sentDialog.setIcon(QMessageBox::Information); + sentDialog.setWindowTitle("Transaction broadcast successfully"); + sentDialog.setText(sentText); + sentDialog.setStandardButtons(QMessageBox::Yes|QMessageBox::Ok); + sentDialog.setDefaultButton(QMessageBox::Ok); + sentDialog.setButtonText( QMessageBox::Yes, "Copy TXID to clipboard" ); + if(sentDialog.exec() == QMessageBox::Yes) + { + // copy TXID to clipboard + GUIUtil::setClipboard(QString::fromStdString(sendTXID.GetHex())); + } + // clear the form + clearFields(); + } +*/ } + diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index 5f80e776bfd1b..85d0628f3dc2e 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -31,6 +31,8 @@ class MetaDExDialog : public QDialog void UpdateSellAddress(); void UpdateBuyAddress(); explicit MetaDExDialog(QWidget *parent = 0); + void setModel(WalletModel *model); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ QWidget *setupTabChain(QWidget *prev); @@ -40,6 +42,7 @@ public slots: void switchButtonClicked(); void sellAddressComboBoxChanged(int idx); void buyAddressComboBoxChanged(int idx); + void sendTrade(bool sell); private: Ui::MetaDExDialog *ui; @@ -48,6 +51,9 @@ public slots: private slots: void buyRecalc(); void sellRecalc(); + void buyTrade(); + void sellTrade(); + signals: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index 55217dd409a13..c51ee43e18790 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -285,7 +285,7 @@ void SendMPDialog::sendMPTransaction() string tmpStrAmount = strAmount.substr(0,pos); string strMsgText = "The amount entered contains a decimal however the property being sent is indivisible.\n\nThe amount entered will be truncated as follows:\n"; strMsgText += "Original amount entered: " + strAmount + "\nAmount that will be sent: " + tmpStrAmount + "\n\n"; - strMsgText += "Do you still wish to process with the transaction?"; + strMsgText += "Do you still wish to proceed with the transaction?"; QString msgText = QString::fromStdString(strMsgText); QMessageBox::StandardButton responseClick; responseClick = QMessageBox::question(this, "Amount truncation warning", msgText, QMessageBox::Yes|QMessageBox::No); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 14c80b347920f..1cdfd66783cd3 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -178,6 +178,7 @@ void WalletView::setWalletModel(WalletModel *walletModel) sendCoinsTab->setModel(walletModel); sendMPTab->setModel(walletModel); balancesView->setModel(walletModel); + metaDExTab->setModel(walletModel); if (walletModel) { From 51983016d6d210ac9abb04a4171b4344e8b3b8d4 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 16 Oct 2014 19:36:56 -0700 Subject: [PATCH 015/141] Minor fixes --- src/qt/metadexdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 4fd6c246a7503..358d98e2a0f5a 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -523,7 +523,7 @@ void MetaDExDialog::sendTrade(bool sell) if (divisible) { buyStr = FormatDivisibleMP(amount); } else { buyStr = FormatIndivisibleMP(amount); } buyStr += " SPT " + propDetails + ""; sellStr = FormatDivisibleMP(totalPrice); - if (testeco) { sellStr += " TMSC #2"; } else { sellStr += " MSC #1"; } + if (testeco) { sellStr += " TMSC"; } else { sellStr += " MSC"; } strMsgText += "Buying: " + buyStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } strMsgText += "\nTotal: " + sellStr; @@ -532,7 +532,7 @@ void MetaDExDialog::sendTrade(bool sell) { buyStr = FormatDivisibleMP(totalPrice); if (divisible) { sellStr = FormatDivisibleMP(amount); } else { sellStr = FormatIndivisibleMP(amount); } - if (testeco) { buyStr += " TMSC #2"; } else { buyStr += " MSC #1"; } + if (testeco) { buyStr += " TMSC"; } else { buyStr += " MSC"; } sellStr += " SPT " + propDetails + ""; strMsgText += "Selling: " + sellStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } From 14acd11ba6898979a79865a68885d42407cc5f93 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Fri, 17 Oct 2014 16:46:01 -0700 Subject: [PATCH 016/141] Add a forced UI refresh every 10 secs --- src/qt/guiconstants.h | 3 +++ src/qt/walletmodel.cpp | 39 ++++++++++++++++++++++++++++++++++++++- src/qt/walletmodel.h | 2 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 5ae4bc833de81..5cfceecf068fd 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -8,6 +8,9 @@ /* Milliseconds between model updates */ static const int MODEL_UPDATE_DELAY = 250; +/* Milliseconds for MasterCore forced updates to catch anything missed - every 10s */ +static const int MASTERCORE_UPDATE_DELAY = 10000; + /* AskPassphraseDialog -- Maximum passphrase length */ static const int MAX_PASSPHRASE_SIZE = 1024; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 37d82ec0633c8..832091c80c450 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -17,7 +17,7 @@ #include "ui_interface.h" #include "wallet.h" #include "walletdb.h" // for BackupWallet - +#include #include #include @@ -42,6 +42,11 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); pollTimer->start(MODEL_UPDATE_DELAY); + // The above timer is too fast for MasterCore usage, we'll have a new one here + updateTimer = new QTimer(this); + connect(updateTimer, SIGNAL(timeout()), this, SLOT(forceUpdateBalances())); + updateTimer->start(MASTERCORE_UPDATE_DELAY); + subscribeToCoreSignals(); } @@ -96,6 +101,38 @@ void WalletModel::updateStatus() emit encryptionStatusChanged(newEncryptionStatus); } +void WalletModel::forceUpdateBalances() +{ + boost::timer t; + // Get required locks upfront. This avoids the GUI from getting stuck on + // periodical polls if the core is holding the locks for a longer time - + // for example, during a wallet rescan. + TRY_LOCK(cs_main, lockMain); + if(!lockMain) + return; + TRY_LOCK(wallet->cs_wallet, lockWallet); + if(!lockWallet) + return; + + qint64 newBalance = getBalance(); + qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + qint64 newImmatureBalance = getImmatureBalance(); + + if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + { + cachedBalance = newBalance; + cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedImmatureBalance = newImmatureBalance; + } + + // force everything to be updated + emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); + if(transactionTableModel) transactionTableModel->updateConfirmations(); + printf("DEBUG: forceUpdate took"); + std::cout << t.elapsed() << std::endl; + printf("\n"); +} + void WalletModel::pollBalanceChanged() { // Get required locks upfront. This avoids the GUI from getting stuck on diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ccf590aaed60c..a6786a1e12e65 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -211,6 +211,7 @@ class WalletModel : public QObject int cachedNumBlocks; QTimer *pollTimer; + QTimer *updateTimer; void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); @@ -249,6 +250,7 @@ public slots: void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status); /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ void pollBalanceChanged(); + void forceUpdateBalances(); }; #endif // WALLETMODEL_H From e14bfc0adee633d537da3b9088a9fb268a13d55b Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 27 Oct 2014 19:55:57 -0700 Subject: [PATCH 017/141] metadex updates --- src/qt/metadexdialog.cpp | 93 +++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 358d98e2a0f5a..f640ae5384282 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -54,6 +54,7 @@ using namespace leveldb; #include "mastercore_dex.h" #include "mastercore_tx.h" #include "mastercore_sp.h" +#include "mastercore_parse_string.h" #include #include @@ -369,11 +370,15 @@ void MetaDExDialog::buyRecalc() bool divisible = isPropertyDivisible(propertyId); bool testeco = false; if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - int64_t buyAmount = strToInt64(ui->buyAmountLE->text().toStdString(),divisible); - int64_t buyPrice = strToInt64(ui->buyPriceLE->text().toStdString(),true); + uint64_t buyAmount = StrToInt64(ui->buyAmountLE->text().toStdString(),divisible); + uint64_t buyPrice = StrToInt64(ui->buyPriceLE->text().toStdString(),true); + if ((0>=buyAmount) || (0>=buyPrice)) { ui->buyTotalLabel->setText("N/A"); return; } // break out before invalid calc + //could result in overflow TODO - uint64_t totalPrice = buyAmount * buyPrice; + uint64_t totalPrice = 0; + if(divisible) { totalPrice = (buyAmount * buyPrice)/COIN; } else { totalPrice = buyAmount * buyPrice; } + string totalLabel = FormatDivisibleMP(totalPrice); if (testeco) { @@ -391,11 +396,14 @@ void MetaDExDialog::sellRecalc() bool divisible = isPropertyDivisible(propertyId); bool testeco = false; if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - int64_t sellAmount = strToInt64(ui->sellAmountLE->text().toStdString(),divisible); - int64_t sellPrice = strToInt64(ui->sellPriceLE->text().toStdString(),true); + uint64_t sellAmount = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); + uint64_t sellPrice = StrToInt64(ui->sellPriceLE->text().toStdString(),true); if ((0>=sellAmount) || (0>=sellPrice)) { ui->sellTotalLabel->setText("N/A"); return; } // break out before invalid calc + //could result in overflow TODO - uint64_t totalPrice = sellAmount * sellPrice; + uint64_t totalPrice; + if(divisible) { totalPrice = (sellAmount * sellPrice)/COIN; } else { totalPrice = sellAmount * sellPrice; } + string totalLabel = FormatDivisibleMP(totalPrice); if (testeco) { @@ -453,22 +461,31 @@ void MetaDExDialog::sendTrade(bool sell) } // use strToInt64 function to get the amounts, using divisibility of the property - int64_t amount = 0; - int64_t price = 0; - if (!sell) + // make fields for trade + uint64_t amountDes; + uint64_t amountSell; + uint64_t price; + unsigned int propertyIdDes; + unsigned int propertyIdSell; + + if(sell) { - amount = strToInt64(ui->buyAmountLE->text().toStdString(),divisible); - price = strToInt64(ui->buyPriceLE->text().toStdString(),true); + amountSell = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); + price = StrToInt64(ui->sellPriceLE->text().toStdString(),true); + if(divisible) { amountDes = (amountSell * price)/COIN; } else { amountDes = amountSell * price; } + if(testeco) { propertyIdDes = 2; } else { propertyIdDes = 1; } + propertyIdSell = global_metadex_market; } else { - amount = strToInt64(ui->sellAmountLE->text().toStdString(),divisible); - price = strToInt64(ui->sellPriceLE->text().toStdString(),true); + amountDes = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); + price = StrToInt64(ui->buyPriceLE->text().toStdString(),true); + if(divisible) { amountSell = (amountDes * price)/COIN; } else { amountSell = amountDes * price; } + if(testeco) { propertyIdSell = 2; } else { propertyIdSell = 1; } + propertyIdDes = global_metadex_market; } - //could result in overflow TODO - uint64_t totalPrice = amount * price; - if ((0>=amount) || (0>=price) || (0>=totalPrice)) + if ((0>=amountDes) || (0>=amountSell) || (0>=propertyIdDes) || (0>=propertyIdSell)) { QMessageBox::critical( this, "Unable to send MetaDEx transaction", "The amount entered is not valid.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); @@ -477,22 +494,8 @@ void MetaDExDialog::sendTrade(bool sell) // check if sending address has enough funds int64_t balanceAvailable = 0; - if (!sell) - { - if (testeco) - { - balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), MASTERCOIN_CURRENCY_TMSC); - } - else - { - balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), MASTERCOIN_CURRENCY_MSC); - } - } - else - { - balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), propertyId); - } - if (((!sell) && (totalPrice>balanceAvailable)) || ((sell) && (amount>balanceAvailable))) + balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), propertyIdSell); + if (amountSell>balanceAvailable) { QMessageBox::critical( this, "Unable to send MetaDEx transaction", "The selected sending address does not have a sufficient balance to cover the amount entered.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); @@ -520,9 +523,9 @@ void MetaDExDialog::sendTrade(bool sell) strMsgText += "Type: Trade Request\nFrom: " + fromAddress.ToString() + "\n\n"; if (!sell) // clicked buy { - if (divisible) { buyStr = FormatDivisibleMP(amount); } else { buyStr = FormatIndivisibleMP(amount); } + if (divisible) { buyStr = FormatDivisibleMP(amountDes); } else { buyStr = FormatIndivisibleMP(amountDes); } buyStr += " SPT " + propDetails + ""; - sellStr = FormatDivisibleMP(totalPrice); + sellStr = FormatDivisibleMP(amountSell); if (testeco) { sellStr += " TMSC"; } else { sellStr += " MSC"; } strMsgText += "Buying: " + buyStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } @@ -530,8 +533,8 @@ void MetaDExDialog::sendTrade(bool sell) } else // clicked sell { - buyStr = FormatDivisibleMP(totalPrice); - if (divisible) { sellStr = FormatDivisibleMP(amount); } else { sellStr = FormatIndivisibleMP(amount); } + buyStr = FormatDivisibleMP(amountDes); + if (divisible) { sellStr = FormatDivisibleMP(amountSell); } else { sellStr = FormatIndivisibleMP(amountSell); } if (testeco) { buyStr += " TMSC"; } else { buyStr += " MSC"; } sellStr += " SPT " + propDetails + ""; strMsgText += "Selling: " + sellStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; @@ -559,10 +562,12 @@ void MetaDExDialog::sendTrade(bool sell) "The transaction has been cancelled.\n\nThe wallet unlock process must be completed to send a transaction." ); return; } -/* + // send the transaction - UI will not send any extra reference amounts at this stage int code = 0; - uint256 sendTXID = send_INTERNAL_1packet(fromAddress.ToString(), refAddress.ToString(), fromAddress.ToString(), propertyId, sendAmount, 0, 0, MSC_TYPE_SIMPLE_SEND, 0, &code); +// uint256 sendTXID = send_INTERNAL_1packet(fromAddress.ToString(), refAddress.ToString(), fromAddress.ToString(), propertyId, sendAmount, 0, 0, MSC_TYPE_SIMPLE_SEND, 0, &code); + uint256 tradeTXID = send_INTERNAL_1packet(fromAddress.ToString(), "", fromAddress.ToString(), propertyIdSell, amountSell, propertyIdDes, amountDes, MSC_TYPE_METADEX, 1, &code); + if (0 != code) { string strCode = boost::lexical_cast(code); @@ -608,12 +613,12 @@ void MetaDExDialog::sendTrade(bool sell) else { // call an update of the balances - set_wallet_totals(); - updateBalances(); +// set_wallet_totals(); +// updateBalances(); // display the result string strSentText = "Your Master Protocol transaction has been sent.\n\nThe transaction ID is:\n\n"; - strSentText += sendTXID.GetHex() + "\n\n"; + strSentText += tradeTXID.GetHex() + "\n\n"; QString sentText = QString::fromStdString(strSentText); QMessageBox sentDialog; sentDialog.setIcon(QMessageBox::Information); @@ -625,12 +630,12 @@ void MetaDExDialog::sendTrade(bool sell) if(sentDialog.exec() == QMessageBox::Yes) { // copy TXID to clipboard - GUIUtil::setClipboard(QString::fromStdString(sendTXID.GetHex())); + GUIUtil::setClipboard(QString::fromStdString(tradeTXID.GetHex())); } // clear the form - clearFields(); +// clearFields(); } -*/ + } From 979b2543b01b9b35745828fbb118efca97933563 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 28 Oct 2014 18:10:57 -0700 Subject: [PATCH 018/141] more metadex work --- src/qt/metadexdialog.cpp | 148 ++++++++++++++++++++++++++++++++------- src/qt/metadexdialog.h | 3 + 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index f640ae5384282..d6457e732353c 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -76,26 +76,7 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->setColumnCount(3); ui->sellList->setColumnCount(3); ui->openOrders->setColumnCount(5); - //dummy data - for(int i=0; i<5; ++i) - { - string strprice = "349.00000006"; - string strtotal = "123456.00000001"; - string strmsctotal = "123456.00000001"; - QString pstr = QString::fromStdString(strprice); - QString tstr = QString::fromStdString(strtotal); - QString mstr = QString::fromStdString(strmsctotal); - if (!ui->buyList) { printf("metadex dialog error\n"); return; } - const int currentRow = ui->buyList->rowCount(); - ui->buyList->setRowCount(currentRow + 1); - ui->buyList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); - ui->buyList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); - ui->buyList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); - ui->sellList->setRowCount(currentRow + 1); - ui->sellList->setItem(currentRow, 0, new QTableWidgetItem(pstr)); - ui->sellList->setItem(currentRow, 1, new QTableWidgetItem(tstr)); - ui->sellList->setItem(currentRow, 2, new QTableWidgetItem(mstr)); - } + //dummy orders const int currentRow = ui->openOrders->rowCount(); ui->openOrders->setRowCount(currentRow + 1); @@ -154,7 +135,15 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : void MetaDExDialog::setModel(WalletModel *model) { this->model = model; -// connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); +printf("setmodel\n"); +} + +void MetaDExDialog::OrderRefresh() +{ + UpdateSellOffers(); + UpdateBuyOffers(); +printf("orderrefresh\n"); } void MetaDExDialog::SwitchMarket() @@ -192,6 +181,115 @@ void MetaDExDialog::SwitchMarket() FullRefresh(); } } + OrderRefresh(); +} + +void MetaDExDialog::UpdateSellOffers() +{ + ui->sellList->clear(); + int rowcount = 0; + bool testeco = isTestEcosystemProperty(global_metadex_market); + for (md_CurrenciesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + // look for the property + if (my_it->first != global_metadex_market) continue; + + // loop prices and list any sells for the right pair +printf("here1\n"); + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + double price = (it->first); + double available = 0; + double total = 0; +printf("here2\n"); + md_Set & indexes = (it->second); + // loop through each entry and sum up any sells for the right pair + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if ( ((testeco) && (obj.getDesCurrency() == 2)) || ((!testeco) && (obj.getDesCurrency() == 1)) ) + { +printf("here3\n"); + available += obj.getAmount(); + total += obj.getAmountDesired(); + } + } + + // done checking this price, if there are any available/total add to pricebook + if ((available > 0) && (total > 0)) + { +printf("here4\n"); + // add to pricebook + QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); + QString tstr = QString::fromStdString(FormatDivisibleMP(available)); + QString mstr = QString::fromStdString(FormatDivisibleMP(total)); + if (!ui->sellList) { printf("metadex dialog error\n"); return; } + ui->sellList->setRowCount(rowcount+2); + ui->sellList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); + ui->sellList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); + ui->sellList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + rowcount += 1; + } + } + } + ui->sellList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); + ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#" + QString::fromStdString(FormatIndivisibleMP(global_metadex_market)))); + if (!testeco) { ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); } else { ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total TMSC")); } +} + +void MetaDExDialog::UpdateBuyOffers() +{ + ui->buyList->clear(); + int rowcount = 0; + bool testeco = isTestEcosystemProperty(global_metadex_market); + for (md_CurrenciesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + // look for the property + unsigned int mapPropertyId = my_it->first; + if ( ((testeco) && (mapPropertyId != 2)) || ((!testeco) && (mapPropertyId != 1)) ) continue; + + // loop prices and list any sells for the right pair +printf("here1\n"); + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + double price = (it->first); + double available = 0; + double total = 0; +printf("here2\n"); + md_Set & indexes = (it->second); + // loop through each entry and sum up any sells for the right pair + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if(obj.getDesCurrency()==global_metadex_market) + { +printf("here3\n"); + available += obj.getAmountDesired(); + total += obj.getAmount(); + } + } + // done checking this price, if there are any available/total add to pricebook + if ((available > 0) && (total > 0)) + { +printf("here4\n"); + // add to pricebook + QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); + QString tstr = QString::fromStdString(FormatDivisibleMP(available)); + QString mstr = QString::fromStdString(FormatDivisibleMP(total)); + if (!ui->buyList) { printf("metadex dialog error\n"); return; } + ui->buyList->setRowCount(rowcount+2); + ui->buyList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); + ui->buyList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); + ui->buyList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + rowcount += 1; + } + } + } + ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); + ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#" + QString::fromStdString(FormatIndivisibleMP(global_metadex_market)))); + if (!testeco) { ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); } else { ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total TMSC")); } } void MetaDExDialog::UpdateSellAddress() @@ -223,12 +321,12 @@ void MetaDExDialog::UpdateBuyAddress() string tokenStr; if (testeco) { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_CURRENCY_TMSC); + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_PROPERTY_TMSC); tokenStr = " TMSC"; } else { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_CURRENCY_MSC); + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_PROPERTY_MSC); tokenStr = " MSC"; } @@ -310,8 +408,8 @@ void MetaDExDialog::FullRefresh() (my_it->second).init(); while (0 != (id = (my_it->second).next())) { - if((id==MASTERCOIN_CURRENCY_MSC) && (!testeco)) { includeAddress=true; break; } - if((id==MASTERCOIN_CURRENCY_TMSC) && (testeco)) { includeAddress=true; break; } + if((id==MASTERCOIN_PROPERTY_MSC) && (!testeco)) { includeAddress=true; break; } + if((id==MASTERCOIN_PROPERTY_TMSC) && (testeco)) { includeAddress=true; break; } } if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId if (!IsMyAddress(address)) continue; //ignore this address, it's not ours diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index 85d0628f3dc2e..aa18b7df0894e 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -30,6 +30,8 @@ class MetaDExDialog : public QDialog void SwitchMarket(); void UpdateSellAddress(); void UpdateBuyAddress(); + void UpdateSellOffers(); + void UpdateBuyOffers(); explicit MetaDExDialog(QWidget *parent = 0); void setModel(WalletModel *model); @@ -43,6 +45,7 @@ public slots: void sellAddressComboBoxChanged(int idx); void buyAddressComboBoxChanged(int idx); void sendTrade(bool sell); + void OrderRefresh(); private: Ui::MetaDExDialog *ui; From b706707ee15e728105df8403e350434a4dd72209 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 30 Oct 2014 20:59:49 -0700 Subject: [PATCH 019/141] Fixing up with latest --- src/qt/forms/metadexdialog.ui | 434 +++++++++++++++++++++------------- src/qt/metadexdialog.cpp | 20 +- 2 files changed, 275 insertions(+), 179 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 07ed90fa4304c..269ad0419821a 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -30,189 +30,283 @@ - - - - 0 - - - - - - 75 - true - - - - Exchange - SP#3/MSC - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 6 - 20 - - - - - - - - true - - - - 0 - 0 - - - - Switch Markets: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 0 - - - - - - - - 0 - 0 - - - - - - - - Switch - - - - - - 10 + 0 0 - 10 - - - - - - - 6 - - 0 - - - QFrame::StyledPanel + + + 0 - - QFrame::Raised + + 10 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 6 - - - 0 - - - - - 0 - - - 0 - - - - - - 75 - true - - - - - - - Your Open Positions - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 80 - - - - 0 - - - 100 - - - - - - - - - + + + + 6 + + + 10 + + + 10 + + + + + 6 + + + 0 + + + + + + 75 + true + + + + SP#3/MSC + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 30 + 20 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Switch + + + + + + + + + + 75 + true + + + + Trade MaidSafeCoin for Mastercoin + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + 10 + 75 + true + + + + 0.000371 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 6 + + + + + + 75 + true + + + + color: red; + + + 7d: -2.345 (-0.68%) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + color: green; + + + 24h: +1.234 (0.34%) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 10 + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + 0 + + + 0 + + + + + + 75 + true + + + + + + + Your Open Positions + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 160 + + + + 0 + + + 100 + + + + + + diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index d6457e732353c..902733cf0d8e0 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -189,7 +189,7 @@ void MetaDExDialog::UpdateSellOffers() ui->sellList->clear(); int rowcount = 0; bool testeco = isTestEcosystemProperty(global_metadex_market); - for (md_CurrenciesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { // look for the property if (my_it->first != global_metadex_market) continue; @@ -199,7 +199,7 @@ printf("here1\n"); md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { - double price = (it->first); + XDOUBLE price = (it->first); double available = 0; double total = 0; printf("here2\n"); @@ -208,11 +208,11 @@ printf("here2\n"); for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) { CMPMetaDEx obj = *it; - if ( ((testeco) && (obj.getDesCurrency() == 2)) || ((!testeco) && (obj.getDesCurrency() == 1)) ) + if ( ((testeco) && (obj.getDesProperty() == 2)) || ((!testeco) && (obj.getDesProperty() == 1)) ) { printf("here3\n"); - available += obj.getAmount(); - total += obj.getAmountDesired(); + available += obj.getAmountDesired(); + total += obj.getAmount(); } } @@ -243,7 +243,7 @@ void MetaDExDialog::UpdateBuyOffers() ui->buyList->clear(); int rowcount = 0; bool testeco = isTestEcosystemProperty(global_metadex_market); - for (md_CurrenciesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { // look for the property unsigned int mapPropertyId = my_it->first; @@ -254,7 +254,7 @@ printf("here1\n"); md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { - double price = (it->first); + XDOUBLE price = (it->first); double available = 0; double total = 0; printf("here2\n"); @@ -263,7 +263,7 @@ printf("here2\n"); for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) { CMPMetaDEx obj = *it; - if(obj.getDesCurrency()==global_metadex_market) + if(obj.getDesProperty()==global_metadex_market) { printf("here3\n"); available += obj.getAmountDesired(); @@ -534,6 +534,8 @@ void MetaDExDialog::sendTrade(bool sell) } // warn if we have to truncate the amount due to a decimal amount for an indivisible property, but allow send to continue + +// need to handle sell too string strAmount = ui->buyAmountLE->text().toStdString(); if (!divisible) { @@ -576,7 +578,7 @@ void MetaDExDialog::sendTrade(bool sell) } else { - amountDes = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); + amountDes = StrToInt64(ui->buyAmountLE->text().toStdString(),divisible); price = StrToInt64(ui->buyPriceLE->text().toStdString(),true); if(divisible) { amountSell = (amountDes * price)/COIN; } else { amountSell = amountDes * price; } if(testeco) { propertyIdSell = 2; } else { propertyIdSell = 1; } From d0f4eda5e3096581607ea15ec370d7e5dcd3a566 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 30 Oct 2014 21:46:09 -0700 Subject: [PATCH 020/141] MetaDEx UI work --- src/qt/forms/metadexdialog.ui | 277 +++++++++++++++++++--------------- src/qt/metadexdialog.cpp | 70 ++++----- src/qt/walletview.cpp | 1 + 3 files changed, 189 insertions(+), 159 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 269ad0419821a..1a0df4eb299ef 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -60,6 +60,22 @@ 10 + + + + + 75 + true + + + + Trade MaidSafeCoin (#3) for Mastercoin + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + @@ -72,31 +88,15 @@ - 75 - true + 50 + false - SP#3/MSC + Switch Markets: - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 30 - 20 - - - - @@ -140,22 +140,32 @@ - - - - - 75 - true - - - - Trade MaidSafeCoin for Mastercoin - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + 0 + + + 0 + @@ -166,7 +176,7 @@ - 0.000371 + SPT#3 / MSC : 0.000371 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -176,8 +186,34 @@ - 6 + 4 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 75 + true + + + + 7d: + + + @@ -190,11 +226,43 @@ color: red; - 7d: -2.345 (-0.68%) + -2.345 (-0.68%) Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 75 + true + + + + 24h: + @@ -209,101 +277,60 @@ color: green; - 24h: +1.234 (0.34%) + +1.234 (0.34%) Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 75 + true + + + + 1h: + + + + + + + + 75 + true + + + + color:green; + + + +1.234 (0.33%) + + + - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 10 - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - 0 - - - 0 - - - - - - 75 - true - - - - - - - Your Open Positions - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 160 - - - - 0 - - - 100 - - - diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 902733cf0d8e0..9663f4564d14a 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -75,32 +75,32 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : //prep lists ui->buyList->setColumnCount(3); ui->sellList->setColumnCount(3); - ui->openOrders->setColumnCount(5); +// ui->openOrders->setColumnCount(5); //dummy orders - const int currentRow = ui->openOrders->rowCount(); - ui->openOrders->setRowCount(currentRow + 1); - ui->openOrders->setItem(currentRow, 0, new QTableWidgetItem("1FakeBitcoinAddressDoNotSend")); - ui->openOrders->setItem(currentRow, 1, new QTableWidgetItem("Sell")); - ui->openOrders->setItem(currentRow, 2, new QTableWidgetItem("0.00004565")); - ui->openOrders->setItem(currentRow, 3, new QTableWidgetItem("345.45643222")); - ui->openOrders->setItem(currentRow, 4, new QTableWidgetItem("0.015770081")); - - ui->openOrders->setHorizontalHeaderItem(0, new QTableWidgetItem("Address")); - ui->openOrders->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); - ui->openOrders->setHorizontalHeaderItem(2, new QTableWidgetItem("Unit Price")); - ui->openOrders->verticalHeader()->setVisible(false); +// const int currentRow = ui->openOrders->rowCount(); +// ui->openOrders->setRowCount(currentRow + 1); +// ui->openOrders->setItem(currentRow, 0, new QTableWidgetItem("1FakeBitcoinAddressDoNotSend")); +// ui->openOrders->setItem(currentRow, 1, new QTableWidgetItem("Sell")); +// ui->openOrders->setItem(currentRow, 2, new QTableWidgetItem("0.00004565")); +// ui->openOrders->setItem(currentRow, 3, new QTableWidgetItem("345.45643222")); +// ui->openOrders->setItem(currentRow, 4, new QTableWidgetItem("0.015770081")); + +// ui->openOrders->setHorizontalHeaderItem(0, new QTableWidgetItem("Address")); +// ui->openOrders->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); +// ui->openOrders->setHorizontalHeaderItem(2, new QTableWidgetItem("Unit Price")); +// ui->openOrders->verticalHeader()->setVisible(false); #if QT_VERSION < 0x050000 - ui->openOrders->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); +// ui->openOrders->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); #else - ui->openOrders->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); +// ui->openOrders->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); #endif - ui->openOrders->horizontalHeader()->resizeSection(1, 60); - ui->openOrders->horizontalHeader()->resizeSection(2, 140); - ui->openOrders->horizontalHeader()->resizeSection(3, 140); - ui->openOrders->horizontalHeader()->resizeSection(4, 140); - ui->openOrders->setShowGrid(false); - ui->openOrders->setSelectionBehavior(QAbstractItemView::SelectRows); +// ui->openOrders->horizontalHeader()->resizeSection(1, 60); +// ui->openOrders->horizontalHeader()->resizeSection(2, 140); +// ui->openOrders->horizontalHeader()->resizeSection(3, 140); +// ui->openOrders->horizontalHeader()->resizeSection(4, 140); +// ui->openOrders->setShowGrid(false); +// ui->openOrders->setSelectionBehavior(QAbstractItemView::SelectRows); ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); @@ -189,10 +189,12 @@ void MetaDExDialog::UpdateSellOffers() ui->sellList->clear(); int rowcount = 0; bool testeco = isTestEcosystemProperty(global_metadex_market); +printf("here\n"); for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { +printf("here0\n"); // look for the property - if (my_it->first != global_metadex_market) continue; + if (my_it->first != global_metadex_market) { printf("continue\n"); continue; } // loop prices and list any sells for the right pair printf("here1\n"); @@ -254,7 +256,7 @@ printf("here1\n"); md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { - XDOUBLE price = (it->first); + XDOUBLE price = (1/it->first); double available = 0; double total = 0; printf("here2\n"); @@ -359,8 +361,8 @@ void MetaDExDialog::FullRefresh() ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("TMSC")); ui->buyTotalLabel->setText("0.00000000 TMSC"); ui->sellTotalLabel->setText("0.00000000 TMSC"); - ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); - ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("TMSC")); +// ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); +// ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("TMSC")); ui->sellTM->setText("TMSC"); ui->buyTM->setText("TMSC"); } @@ -371,8 +373,8 @@ void MetaDExDialog::FullRefresh() ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("MSC")); ui->buyTotalLabel->setText("0.00000000 MSC"); ui->sellTotalLabel->setText("0.00000000 MSC"); - ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); - ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("MSC")); +// ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); +// ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("MSC")); ui->sellTM->setText("MSC"); ui->buyTM->setText("MSC"); } @@ -427,13 +429,13 @@ void MetaDExDialog::FullRefresh() UpdateBuyAddress(); // silly sizing - QRect rect = ui->openOrders->geometry(); - int tableHeight = 2 + ui->openOrders->horizontalHeader()->height(); - for(int i = 0; i < ui->openOrders->rowCount(); i++){ - tableHeight += ui->openOrders->rowHeight(i); - } - rect.setHeight(tableHeight); - ui->openOrders->setGeometry(rect); +// QRect rect = ui->openOrders->geometry(); +// int tableHeight = 2 + ui->openOrders->horizontalHeader()->height(); +// for(int i = 0; i < ui->openOrders->rowCount(); i++){ +// tableHeight += ui->openOrders->rowHeight(i); +// } +// rect.setHeight(tableHeight); +// ui->openOrders->setGeometry(rect); } void MetaDExDialog::buyAddressComboBoxChanged(int idx) diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 1cdfd66783cd3..3f3db4178636a 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -99,6 +99,7 @@ WalletView::WalletView(QWidget *parent): QTabWidget *exTabHolder = new QTabWidget(); exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); exTabHolder->addTab(metaDExTab,tr("Trade Mastercoin/Smart Properties")); + exTabHolder->addTab(new QWidget(),tr("Open Orders")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); From 4b8b5d4ebd5b55e50cb3b3d81eda601ccbf3f037 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 17:33:07 -0800 Subject: [PATCH 021/141] Refresh metadex UI, swap buy/sell books and label --- src/qt/forms/metadexdialog.ui | 98 +++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 1a0df4eb299ef..99af288207ecb 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -491,13 +491,6 @@ 0 - - - - Total Price: - - - @@ -511,6 +504,13 @@ + + + + Total Price: + + + @@ -537,7 +537,40 @@ - + + + 0 + + + + + + 75 + true + + + + SELL OFFERS + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 @@ -699,13 +732,6 @@ 0 - - - - Total Price: - - - @@ -719,6 +745,13 @@ + + + + Total Price: + + + @@ -745,7 +778,40 @@ - + + + 0 + + + + + + 75 + true + + + + BUY OFFERS + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + From c5e5e76832f4df8d8bbee72a845e21651cd5fd51 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 17:42:05 -0800 Subject: [PATCH 022/141] Add clickable offers --- src/qt/metadexdialog.cpp | 13 +++++++++++++ src/qt/metadexdialog.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 9663f4564d14a..26183af4e69ae 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -127,6 +127,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : connect(ui->sellPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); connect(ui->buyAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); connect(ui->buyPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); + connect(ui->sellList, SIGNAL(cellClicked(int,int)), this, SLOT(sellClicked(int,int))); + connect(ui->buyList, SIGNAL(cellClicked(int,int)), this, SLOT(buyClicked(int,int))); FullRefresh(); @@ -184,6 +186,17 @@ void MetaDExDialog::SwitchMarket() OrderRefresh(); } + +void MetaDExDialog::buyClicked(int row, int col) +{ +printf("clickedbuyoffer\n"); +} + +void MetaDExDialog::sellClicked(int row, int col) +{ +printf("clickedselloffer\n"); +} + void MetaDExDialog::UpdateSellOffers() { ui->sellList->clear(); diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index aa18b7df0894e..e91ebd761390c 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -44,6 +44,8 @@ public slots: void switchButtonClicked(); void sellAddressComboBoxChanged(int idx); void buyAddressComboBoxChanged(int idx); + void sellClicked(int row, int col); + void buyClicked(int row, int col); void sendTrade(bool sell); void OrderRefresh(); From 8d97e2e851d03d2b571c6bb0bb79fb847ec5be5f Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 17:48:54 -0800 Subject: [PATCH 023/141] Make order books non-editable --- src/qt/metadexdialog.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 26183af4e69ae..e5333517b3a97 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -109,6 +109,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->buyList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); ui->buyList->setShowGrid(false); ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->buyList->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->buyList->setSelectionMode(QAbstractItemView::SingleSelection); ui->sellList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); @@ -117,6 +119,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->sellList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); ui->sellList->setShowGrid(false); ui->sellList->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->sellList->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->sellList->setSelectionMode(QAbstractItemView::SingleSelection); connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); connect(ui->buyButton, SIGNAL(clicked()), this, SLOT(buyTrade())); From 9114501f51f63a12c6938d5f10e96366acc3af76 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 17:52:40 -0800 Subject: [PATCH 024/141] Change forced refresh to 60 secs, balance/block triggers should refresh --- src/qt/guiconstants.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 5cfceecf068fd..7ed52d99ccf7e 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -9,7 +9,8 @@ static const int MODEL_UPDATE_DELAY = 250; /* Milliseconds for MasterCore forced updates to catch anything missed - every 10s */ -static const int MASTERCORE_UPDATE_DELAY = 10000; +/* Updated to 60 seconds, balance/block triggers should be getting all the refreshes in */ +static const int MASTERCORE_UPDATE_DELAY = 60000; /* AskPassphraseDialog -- Maximum passphrase length */ static const int MAX_PASSPHRASE_SIZE = 1024; From 1881776d50de334f90c64282dd20d28b603eb647 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 18:35:42 -0800 Subject: [PATCH 025/141] Flag own orders (or partof) with bold in orderbook --- src/qt/metadexdialog.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index e5333517b3a97..4e1a40454c327 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -221,6 +221,7 @@ printf("here1\n"); XDOUBLE price = (it->first); double available = 0; double total = 0; + bool includesMe = false; printf("here2\n"); md_Set & indexes = (it->second); // loop through each entry and sum up any sells for the right pair @@ -232,6 +233,7 @@ printf("here2\n"); printf("here3\n"); available += obj.getAmountDesired(); total += obj.getAmount(); + if(IsMyAddress(obj.getAddr())) includesMe = true; } } @@ -248,6 +250,14 @@ printf("here4\n"); ui->sellList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); ui->sellList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); ui->sellList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + if(includesMe) + { + QFont font; + font.setBold(true); + ui->sellList->item(rowcount, 0)->setFont(font); + ui->sellList->item(rowcount, 1)->setFont(font); + ui->sellList->item(rowcount, 2)->setFont(font); + } rowcount += 1; } } @@ -276,6 +286,7 @@ printf("here1\n"); XDOUBLE price = (1/it->first); double available = 0; double total = 0; + bool includesMe = false; printf("here2\n"); md_Set & indexes = (it->second); // loop through each entry and sum up any sells for the right pair @@ -287,6 +298,7 @@ printf("here2\n"); printf("here3\n"); available += obj.getAmountDesired(); total += obj.getAmount(); + if(IsMyAddress(obj.getAddr())) includesMe = true; } } // done checking this price, if there are any available/total add to pricebook @@ -302,6 +314,14 @@ printf("here4\n"); ui->buyList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); ui->buyList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); ui->buyList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + if(includesMe) + { + QFont font; + font.setBold(true); + ui->buyList->item(rowcount, 0)->setFont(font); + ui->buyList->item(rowcount, 1)->setFont(font); + ui->buyList->item(rowcount, 2)->setFont(font); + } rowcount += 1; } } From 5118474bb114f083b6d1e45f429c1ea2e8300431 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 3 Nov 2014 18:37:05 -0800 Subject: [PATCH 026/141] Remove debugging printfs --- src/qt/metadexdialog.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 4e1a40454c327..7902392b05bc9 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -142,14 +142,12 @@ void MetaDExDialog::setModel(WalletModel *model) { this->model = model; connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); -printf("setmodel\n"); } void MetaDExDialog::OrderRefresh() { UpdateSellOffers(); UpdateBuyOffers(); -printf("orderrefresh\n"); } void MetaDExDialog::SwitchMarket() @@ -206,15 +204,12 @@ void MetaDExDialog::UpdateSellOffers() ui->sellList->clear(); int rowcount = 0; bool testeco = isTestEcosystemProperty(global_metadex_market); -printf("here\n"); for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { -printf("here0\n"); // look for the property if (my_it->first != global_metadex_market) { printf("continue\n"); continue; } // loop prices and list any sells for the right pair -printf("here1\n"); md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { @@ -222,7 +217,6 @@ printf("here1\n"); double available = 0; double total = 0; bool includesMe = false; -printf("here2\n"); md_Set & indexes = (it->second); // loop through each entry and sum up any sells for the right pair for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) @@ -230,7 +224,6 @@ printf("here2\n"); CMPMetaDEx obj = *it; if ( ((testeco) && (obj.getDesProperty() == 2)) || ((!testeco) && (obj.getDesProperty() == 1)) ) { -printf("here3\n"); available += obj.getAmountDesired(); total += obj.getAmount(); if(IsMyAddress(obj.getAddr())) includesMe = true; @@ -240,7 +233,6 @@ printf("here3\n"); // done checking this price, if there are any available/total add to pricebook if ((available > 0) && (total > 0)) { -printf("here4\n"); // add to pricebook QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); QString tstr = QString::fromStdString(FormatDivisibleMP(available)); @@ -279,7 +271,6 @@ void MetaDExDialog::UpdateBuyOffers() if ( ((testeco) && (mapPropertyId != 2)) || ((!testeco) && (mapPropertyId != 1)) ) continue; // loop prices and list any sells for the right pair -printf("here1\n"); md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { @@ -287,7 +278,6 @@ printf("here1\n"); double available = 0; double total = 0; bool includesMe = false; -printf("here2\n"); md_Set & indexes = (it->second); // loop through each entry and sum up any sells for the right pair for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) @@ -295,7 +285,6 @@ printf("here2\n"); CMPMetaDEx obj = *it; if(obj.getDesProperty()==global_metadex_market) { -printf("here3\n"); available += obj.getAmountDesired(); total += obj.getAmount(); if(IsMyAddress(obj.getAddr())) includesMe = true; @@ -304,7 +293,6 @@ printf("here3\n"); // done checking this price, if there are any available/total add to pricebook if ((available > 0) && (total > 0)) { -printf("here4\n"); // add to pricebook QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); QString tstr = QString::fromStdString(FormatDivisibleMP(available)); From b1a451e4c99b9c6f48823ba597ca0ac8f96a3634 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 4 Nov 2014 14:49:28 -0800 Subject: [PATCH 027/141] Fix renames --- src/qt/forms/metadexdialog.ui | 19 +++++++++++++++++++ src/qt/metadexdialog.cpp | 20 +++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 99af288207ecb..917871472e16e 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -820,6 +820,25 @@ + + + + + 75 + true + + + + color:rgb(167, 125, 19) + + + * YOU HAVE TRANSACTIONS WAITING FOR CONFIRMATION * + + + Qt::AlignCenter + + + diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 7902392b05bc9..4c73565550f20 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -72,6 +72,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : //open global_metadex_market = 3; + //hide pending +// ui->pendingLabel->setVisible(false); //prep lists ui->buyList->setColumnCount(3); ui->sellList->setColumnCount(3); @@ -148,6 +150,14 @@ void MetaDExDialog::OrderRefresh() { UpdateSellOffers(); UpdateBuyOffers(); + // check for pending transactions, could be more filtered to just trades here + bool pending = false; +// for(PendingMap::iterator my_it = my_pending.begin(); my_it != my_pending.end(); ++my_it) +// { + // if we get here there are pending transactions in the wallet, flag warning to MetaDEx +// pending = true; +// } +// if(pending) { ui->pendingLabel->setVisible(true); } else { ui->pendingLabel->setVisible(false); } } void MetaDExDialog::SwitchMarket() @@ -207,7 +217,7 @@ void MetaDExDialog::UpdateSellOffers() for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { // look for the property - if (my_it->first != global_metadex_market) { printf("continue\n"); continue; } + if (my_it->first != global_metadex_market) { continue; } // loop prices and list any sells for the right pair md_PricesMap & prices = my_it->second; @@ -348,12 +358,12 @@ void MetaDExDialog::UpdateBuyAddress() string tokenStr; if (testeco) { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_PROPERTY_TMSC); + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), OMNI_PROPERTY_TMSC); tokenStr = " TMSC"; } else { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), MASTERCOIN_PROPERTY_MSC); + balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), OMNI_PROPERTY_MSC); tokenStr = " MSC"; } @@ -435,8 +445,8 @@ void MetaDExDialog::FullRefresh() (my_it->second).init(); while (0 != (id = (my_it->second).next())) { - if((id==MASTERCOIN_PROPERTY_MSC) && (!testeco)) { includeAddress=true; break; } - if((id==MASTERCOIN_PROPERTY_TMSC) && (testeco)) { includeAddress=true; break; } + if((id==OMNI_PROPERTY_MSC) && (!testeco)) { includeAddress=true; break; } + if((id==OMNI_PROPERTY_TMSC) && (testeco)) { includeAddress=true; break; } } if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId if (!IsMyAddress(address)) continue; //ignore this address, it's not ours From 9a20d09d1480610dc05937c1ff2a073a51fd1269 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 14:57:18 -0800 Subject: [PATCH 028/141] Fix namespace ordering --- src/qt/lookupspdialog.cpp | 2 +- src/qt/metadexdialog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp index a5fe361c3e535..9ac619dfd4993 100644 --- a/src/qt/lookupspdialog.cpp +++ b/src/qt/lookupspdialog.cpp @@ -40,6 +40,7 @@ #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; #include "mastercore.h" using namespace mastercore; @@ -47,7 +48,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 4c73565550f20..59550fcb73fc3 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -40,6 +40,7 @@ #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; #include "mastercore.h" using namespace mastercore; @@ -47,7 +48,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using From 6916aa92c5ebedf34eb49ed7e045d659c9df5259 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 15:35:08 -0800 Subject: [PATCH 029/141] Tab out transaction history and add utility page --- src/qt/metadexdialog.cpp | 4 ++-- src/qt/walletview.cpp | 28 +++++++++++++++++++++++++--- src/qt/walletview.h | 7 +++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 59550fcb73fc3..d4cbcca89fac6 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -224,8 +224,8 @@ void MetaDExDialog::UpdateSellOffers() for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { XDOUBLE price = (it->first); - double available = 0; - double total = 0; + int64_t available = 0; + int64_t total = 0; bool includesMe = false; md_Set & indexes = (it->second); // loop through each entry and sum up any sells for the right pair diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 3f3db4178636a..b69bc87adc832 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -63,6 +63,12 @@ WalletView::WalletView(QWidget *parent): balancesPage->setLayout(bvbox); // transactions page + // bitcoin transactions in second tab, MP transactions in first + //masterprotocol + mpTXTab = new QWidget(); + + //bitcoin + bitcoinTXTab = new QWidget(this); QVBoxLayout *vbox = new QVBoxLayout(); QHBoxLayout *hbox_buttons = new QHBoxLayout(); transactionView = new TransactionView(this); @@ -75,12 +81,20 @@ WalletView::WalletView(QWidget *parent): hbox_buttons->addStretch(); hbox_buttons->addWidget(exportButton); vbox->addLayout(hbox_buttons); - transactionsPage->setLayout(vbox); + bitcoinTXTab->setLayout(vbox); + transactionsPage = new QWidget(this); + QVBoxLayout *txvbox = new QVBoxLayout(); + QTabWidget *txTabHolder = new QTabWidget(); + txTabHolder->addTab(mpTXTab,tr("Master Protocol")); + txTabHolder->addTab(bitcoinTXTab,tr("Bitcoin")); + txvbox->addWidget(txTabHolder); + transactionsPage->setLayout(txvbox); + + // receive page receiveCoinsPage = new ReceiveCoinsDialog(); // sending page - //sendCoinsPage = new SendCoinsDialog(); sendCoinsPage = new QWidget(this); QVBoxLayout *svbox = new QVBoxLayout(); sendCoinsTab = new SendCoinsDialog(); @@ -88,7 +102,6 @@ WalletView::WalletView(QWidget *parent): QTabWidget *tabHolder = new QTabWidget(); tabHolder->addTab(sendMPTab,tr("Master Protocol")); tabHolder->addTab(sendCoinsTab,tr("Bitcoin")); -// tabHolder->addTab(new QWidget(),tr("Smart Properties")); svbox->addWidget(tabHolder); sendCoinsPage->setLayout(svbox); @@ -115,6 +128,9 @@ WalletView::WalletView(QWidget *parent): spvbox->addWidget(spTabHolder); smartPropertyPage->setLayout(spvbox); + // utility page + utilityPage = new QWidget(this); + // add pages addWidget(overviewPage); addWidget(balancesPage); @@ -123,6 +139,7 @@ WalletView::WalletView(QWidget *parent): addWidget(sendCoinsPage); addWidget(exchangePage); addWidget(smartPropertyPage); + addWidget(utilityPage); // 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))); @@ -243,6 +260,11 @@ void WalletView::gotoExchangePage() setCurrentWidget(exchangePage); } +void WalletView::gotoUtilityPage() +{ + setCurrentWidget(utilityPage); +} + void WalletView::gotoSmartPropertyPage() { setCurrentWidget(smartPropertyPage); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index dbf2f14cb1128..fb3c6576146ea 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -63,6 +63,7 @@ class WalletView : public QStackedWidget QWidget *balancesPage; QWidget *exchangePage; QWidget *smartPropertyPage; + QWidget *utilityPage; ReceiveCoinsDialog *receiveCoinsPage; // SendCoinsDialog *sendCoinsPage; @@ -73,7 +74,8 @@ class WalletView : public QStackedWidget MetaDExDialog *metaDExTab; TransactionView *transactionView; BalancesView *balancesView; - + QWidget *mpTXTab; + QWidget *bitcoinTXTab; QProgressDialog *progressDialog; public slots: @@ -91,7 +93,8 @@ public slots: void gotoReceiveCoinsPage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); - + /** Switch to utility page */ + void gotoUtilityPage(); /** Show Sign/Verify Message dialog and switch to sign message tab */ void gotoSignMessageTab(QString addr = ""); /** Show Sign/Verify Message dialog and switch to verify message tab */ From 7df633ed794cbf5408b6a7ef6613e01bd9afb431 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 15:55:58 -0800 Subject: [PATCH 030/141] Rename to toolbox, add icon and fix up --- src/qt/Makefile.am | 1 + src/qt/bitcoin.qrc | 1 + src/qt/bitcoingui.cpp | 17 +++++++++++++++++ src/qt/bitcoingui.h | 3 +++ src/qt/res/icons/mp_toolbox.png | Bin 0 -> 2200 bytes src/qt/walletframe.cpp | 7 +++++++ src/qt/walletframe.h | 2 ++ src/qt/walletview.cpp | 10 +++++----- src/qt/walletview.h | 4 ++-- 9 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/qt/res/icons/mp_toolbox.png diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index d0d91f5bab14a..e7608bd87b5ce 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -228,6 +228,7 @@ BITCOIN_QT_H = \ RES_ICONS = \ res/icons/mp_exchange.png \ + res/icons/mp_toolbox.png \ res/icons/mp_sp.png \ res/icons/mp_balances.png \ res/icons/mp_history.png \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index b32915f086a58..12174de1dd553 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,6 +1,7 @@ res/icons/mp_balances.png + res/icons/mp_toolbox.png res/icons/mp_exchange.png res/icons/mp_sp.png res/icons/bitcoin.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index a785b89a1cda4..99212790a7889 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -268,6 +268,13 @@ void BitcoinGUI::createActions(bool fIsTestnet) historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_7)); tabGroup->addAction(historyAction); + toolboxAction = new QAction(QIcon(":/icons/toolbox"), tr("&Toolbox"), this); + toolboxAction->setStatusTip(tr("Tools to obtain varions Master Protocol information and transaction information")); + toolboxAction->setToolTip(toolboxAction->statusTip()); + toolboxAction->setCheckable(true); + toolboxAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_8)); + tabGroup->addAction(toolboxAction); + // 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. connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); @@ -284,6 +291,8 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(exchangeAction, SIGNAL(triggered()), this, SLOT(gotoExchangePage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); + connect(toolboxAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(toolboxAction, SIGNAL(triggered()), this, SLOT(gotoToolboxPage())); quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setStatusTip(tr("Quit application")); @@ -416,6 +425,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(exchangeAction); toolbar->addAction(smartPropertyAction); toolbar->addAction(historyAction); + toolbar->addAction(toolboxAction); overviewAction->setChecked(true); } } @@ -483,6 +493,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) exchangeAction->setEnabled(enabled); smartPropertyAction->setEnabled(enabled); historyAction->setEnabled(enabled); + toolboxAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled); changePassphraseAction->setEnabled(enabled); @@ -618,6 +629,12 @@ void BitcoinGUI::gotoHistoryPage() if (walletFrame) walletFrame->gotoHistoryPage(); } +void BitcoinGUI::gotoToolboxPage() +{ + toolboxAction->setChecked(true); + if (walletFrame) walletFrame->gotoToolboxPage(); +} + void BitcoinGUI::gotoReceiveCoinsPage() { receiveCoinsAction->setChecked(true); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index f916b5355d710..d8c621914bbbc 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -79,6 +79,7 @@ class BitcoinGUI : public QMainWindow QAction *balancesAction; QAction *historyAction; QAction *quitAction; + QAction *toolboxAction; QAction *sendCoinsAction; QAction *exchangeAction; QAction *smartPropertyAction; @@ -165,6 +166,8 @@ private slots: void gotoBalancesPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); + /** Switch to utility page */ + void gotoToolboxPage(); /** Switch to exchange page */ void gotoExchangePage(); /** Switch to the smart property page */ diff --git a/src/qt/res/icons/mp_toolbox.png b/src/qt/res/icons/mp_toolbox.png new file mode 100644 index 0000000000000000000000000000000000000000..a56df6e912d8cd28b5b0ad8df455e49abcb39b56 GIT binary patch literal 2200 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 a0R{k3m&W}-HC=E30000gotoHistoryPage(); } +void WalletFrame::gotoToolboxPage() +{ + QMap::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoToolboxPage(); +} + void WalletFrame::gotoReceiveCoinsPage() { QMap::const_iterator i; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 372217e27df70..391d0adb454d3 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -58,6 +58,8 @@ public slots: void gotoSmartPropertyPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); + /** Switch to utility page */ + void gotoToolboxPage(); /** 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 b69bc87adc832..8277952d72e4f 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -128,8 +128,8 @@ WalletView::WalletView(QWidget *parent): spvbox->addWidget(spTabHolder); smartPropertyPage->setLayout(spvbox); - // utility page - utilityPage = new QWidget(this); + // toolbox page + toolboxPage = new QWidget(this); // add pages addWidget(overviewPage); @@ -139,7 +139,7 @@ WalletView::WalletView(QWidget *parent): addWidget(sendCoinsPage); addWidget(exchangePage); addWidget(smartPropertyPage); - addWidget(utilityPage); + addWidget(toolboxPage); // 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))); @@ -260,9 +260,9 @@ void WalletView::gotoExchangePage() setCurrentWidget(exchangePage); } -void WalletView::gotoUtilityPage() +void WalletView::gotoToolboxPage() { - setCurrentWidget(utilityPage); + setCurrentWidget(toolboxPage); } void WalletView::gotoSmartPropertyPage() diff --git a/src/qt/walletview.h b/src/qt/walletview.h index fb3c6576146ea..d0fb62120331f 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -63,7 +63,7 @@ class WalletView : public QStackedWidget QWidget *balancesPage; QWidget *exchangePage; QWidget *smartPropertyPage; - QWidget *utilityPage; + QWidget *toolboxPage; ReceiveCoinsDialog *receiveCoinsPage; // SendCoinsDialog *sendCoinsPage; @@ -94,7 +94,7 @@ public slots: /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); /** Switch to utility page */ - void gotoUtilityPage(); + void gotoToolboxPage(); /** Show Sign/Verify Message dialog and switch to sign message tab */ void gotoSignMessageTab(QString addr = ""); /** Show Sign/Verify Message dialog and switch to verify message tab */ From fdf7a479ee21fd44329279999039f5509deb6ad0 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 17:09:29 -0800 Subject: [PATCH 031/141] Add order history initials --- src/qt/Makefile.am | 4 ++++ src/qt/walletview.cpp | 5 +++-- src/qt/walletview.h | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index e7608bd87b5ce..fa0929517cc9f 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -101,6 +101,7 @@ QT_FORMS_UI = \ forms/sendcoinsdialog.ui \ forms/sendcoinsentry.ui \ forms/sendmpdialog.ui \ + forms/orderhistorydialog.ui \ forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/signverifymessagedialog.ui \ @@ -140,6 +141,7 @@ QT_MOC_CPP = \ moc_sendcoinsentry.cpp \ moc_sendmpdialog.cpp \ moc_metadexdialog.cpp \ + moc_orderhistorydialog.cpp \ moc_lookupspdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ @@ -208,6 +210,7 @@ BITCOIN_QT_H = \ sendcoinsentry.h \ sendmpdialog.h \ metadexdialog.h \ + orderhistorydialog.h \ lookupspdialog.h \ signverifymessagedialog.h \ splashscreen.h \ @@ -320,6 +323,7 @@ BITCOIN_QT_CPP += \ sendcoinsentry.cpp \ sendmpdialog.cpp \ metadexdialog.cpp \ + orderhistorydialog.cpp \ lookupspdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 8277952d72e4f..e2f4fa3339c3f 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -21,7 +21,7 @@ #include "transactionview.h" #include "balancesview.h" #include "walletmodel.h" - +#include "orderhistorydialog.h" #include "ui_interface.h" #include @@ -110,9 +110,10 @@ WalletView::WalletView(QWidget *parent): QVBoxLayout *exvbox = new QVBoxLayout(); metaDExTab = new MetaDExDialog(); QTabWidget *exTabHolder = new QTabWidget(); + orderHistoryTab = new OrderHistoryDialog; exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); exTabHolder->addTab(metaDExTab,tr("Trade Mastercoin/Smart Properties")); - exTabHolder->addTab(new QWidget(),tr("Open Orders")); + exTabHolder->addTab(orderHistoryTab,tr("Open Orders")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index d0fb62120331f..5769ab63f38bb 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -13,6 +13,7 @@ class OverviewPage; class ReceiveCoinsDialog; class SendCoinsDialog; class SendMPDialog; +class OrderHistoryDialog; class LookupSPDialog; class MetaDExDialog; class SendCoinsRecipient; @@ -71,6 +72,7 @@ class WalletView : public QStackedWidget SendCoinsDialog *sendCoinsTab; SendMPDialog *sendMPTab; LookupSPDialog *spLookupTab; + OrderHistoryDialog *orderHistoryTab; MetaDExDialog *metaDExTab; TransactionView *transactionView; BalancesView *balancesView; From 5dcfb19d23b5fa0ae44c188e42d0d77c11c94a14 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 17:10:13 -0800 Subject: [PATCH 032/141] missing files for orderHistoryDialog --- src/qt/forms/orderhistorydialog.ui | 31 ++++++++++++ src/qt/orderhistorydialog.cpp | 78 ++++++++++++++++++++++++++++++ src/qt/orderhistorydialog.h | 53 ++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 src/qt/forms/orderhistorydialog.ui create mode 100644 src/qt/orderhistorydialog.cpp create mode 100644 src/qt/orderhistorydialog.h diff --git a/src/qt/forms/orderhistorydialog.ui b/src/qt/forms/orderhistorydialog.ui new file mode 100644 index 0000000000000..9997070a670dc --- /dev/null +++ b/src/qt/forms/orderhistorydialog.ui @@ -0,0 +1,31 @@ + + + orderHistoryDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + 0 + + + + + + + + + + + diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp new file mode 100644 index 0000000000000..91cb021fa30b4 --- /dev/null +++ b/src/qt/orderhistorydialog.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "orderhistorydialog.h" +#include "ui_orderhistorydialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +using namespace json_spirit; +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" +#include "mastercore_parse_string.h" + +#include +#include +#include +#include + +OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::orderHistoryDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; +} + +void OrderHistoryDialog::setModel(WalletModel *model) +{ + this->model = model; + //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); +} + diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h new file mode 100644 index 0000000000000..ea858b5971b8a --- /dev/null +++ b/src/qt/orderhistorydialog.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef ORDERHISTORYDIALOG_H +#define ORDERHISTORYDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class orderHistoryDialog; +} + +/** Dialog for looking up Master Protocol tokens */ +class OrderHistoryDialog : public QDialog +{ + Q_OBJECT + +public: + //void FullRefresh(); + explicit OrderHistoryDialog(QWidget *parent = 0); + void setModel(WalletModel *model); + + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + +public slots: + //void switchButtonClicked(); + +private: + Ui::orderHistoryDialog *ui; + WalletModel *model; + +private slots: + //void buyRecalc(); + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // ORDERHISTORYDIALOG_H From 9591a7e82ad642adfeb0baa31c3efe32bd617e2f Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 17:10:33 -0800 Subject: [PATCH 033/141] initials for orderListDelegate --- src/qt/orderlistdelegate.cpp | 87 ++++++++++++++++++++++++++++++++++++ src/qt/orderlistdelegate.h | 14 ++++++ 2 files changed, 101 insertions(+) create mode 100644 src/qt/orderlistdelegate.cpp create mode 100644 src/qt/orderlistdelegate.h diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp new file mode 100644 index 0000000000000..644ff68fd4ee1 --- /dev/null +++ b/src/qt/orderlistdelegate.cpp @@ -0,0 +1,87 @@ +#include "orderlistdelegate.h" + + ListDelegate::ListDelegate(QObject *parent) + { + + } + + void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const{ + QRect r = option.rect; + + //Color: #C4C4C4 + QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); + + //Color: #005A83 + QPen lineMarkedPen(QColor::fromRgb(0,90,131), 1, Qt::SolidLine); + + //Color: #333 + QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); + + //Color: #fff + QPen fontMarkedPen(Qt::white, 1, Qt::SolidLine); + + if(option.state & QStyle::State_Selected){ + QLinearGradient gradientSelected(r.left(),r.top(),r.left(),r.height()+r.top()); + gradientSelected.setColorAt(0.0, QColor::fromRgb(119,213,247)); + gradientSelected.setColorAt(0.9, QColor::fromRgb(27,134,183)); + gradientSelected.setColorAt(1.0, QColor::fromRgb(0,120,174)); + painter->setBrush(gradientSelected); + painter->drawRect(r); + + //BORDER + painter->setPen(lineMarkedPen); + painter->drawLine(r.topLeft(),r.topRight()); + painter->drawLine(r.topRight(),r.bottomRight()); + painter->drawLine(r.bottomLeft(),r.bottomRight()); + painter->drawLine(r.topLeft(),r.bottomLeft()); + + painter->setPen(fontMarkedPen); + + } else { + //BACKGROUND + //ALTERNATING COLORS + painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); + painter->drawRect(r); + + //BORDER + painter->setPen(linePen); + painter->drawLine(r.topLeft(),r.topRight()); + painter->drawLine(r.topRight(),r.bottomRight()); + painter->drawLine(r.bottomLeft(),r.bottomRight()); + painter->drawLine(r.topLeft(),r.bottomLeft()); + + painter->setPen(fontPen); + } + + //GET TITLE, DESCRIPTION AND ICON + QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); + QString title = index.data(Qt::DisplayRole).toString(); + QString description = index.data(Qt::UserRole + 1).toString(); + + int imageSpace = 10; + if (!ic.isNull()) { + //ICON + r = option.rect.adjusted(5, 10, -10, -10); + ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); + imageSpace = 55; + } + + //TITLE + r = option.rect.adjusted(imageSpace, 0, -10, -30); + painter->setFont( QFont( "Lucida Grande", 6, QFont::Normal ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, title, &r); + + //DESCRIPTION + r = option.rect.adjusted(imageSpace, 30, -10, 0); + painter->setFont( QFont( "Lucida Grande", 5, QFont::Normal ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, description, &r); + } + + QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const{ + return QSize(200, 60); // very dumb value + } + + ListDelegate::~ListDelegate() + { + + } diff --git a/src/qt/orderlistdelegate.h b/src/qt/orderlistdelegate.h new file mode 100644 index 0000000000000..c1912d979825f --- /dev/null +++ b/src/qt/orderlistdelegate.h @@ -0,0 +1,14 @@ +#include +#include + +class ListDelegate : public QAbstractItemDelegate +{ + public: + ListDelegate(QObject *parent = 0); + + void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; + + virtual ~ListDelegate(); + +}; From 426076ceef115c270d8843849690549597ce17c2 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 17:14:29 -0800 Subject: [PATCH 034/141] Correct tabs --- src/qt/walletview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index e2f4fa3339c3f..61ac3221cc8b8 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -111,9 +111,9 @@ WalletView::WalletView(QWidget *parent): metaDExTab = new MetaDExDialog(); QTabWidget *exTabHolder = new QTabWidget(); orderHistoryTab = new OrderHistoryDialog; - exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); + //exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); not yet implemented exTabHolder->addTab(metaDExTab,tr("Trade Mastercoin/Smart Properties")); - exTabHolder->addTab(orderHistoryTab,tr("Open Orders")); + exTabHolder->addTab(orderHistoryTab,tr("Order History")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); From 2cd3dfd5a22a180303a11c81ffc5bf45908bd2a3 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 17:36:51 -0800 Subject: [PATCH 035/141] Adding listdelegate for formatting of history --- src/qt/Makefile.am | 3 ++ src/qt/orderhistorydialog.cpp | 12 +++++++ src/qt/orderlistdelegate.cpp | 68 ++++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index fa0929517cc9f..0333b1aa39ed3 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -142,6 +142,7 @@ QT_MOC_CPP = \ moc_sendmpdialog.cpp \ moc_metadexdialog.cpp \ moc_orderhistorydialog.cpp \ + moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ @@ -212,6 +213,7 @@ BITCOIN_QT_H = \ metadexdialog.h \ orderhistorydialog.h \ lookupspdialog.h \ + orderlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ trafficgraphwidget.h \ @@ -324,6 +326,7 @@ BITCOIN_QT_CPP += \ sendmpdialog.cpp \ metadexdialog.cpp \ orderhistorydialog.cpp \ + orderlistdelegate.cpp \ lookupspdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 91cb021fa30b4..feca2bd7532cb 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -61,6 +61,8 @@ using namespace leveldb; #include #include +#include "orderlistdelegate.h" + OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : QDialog(parent), ui(new Ui::orderHistoryDialog), @@ -68,6 +70,16 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : { ui->setupUi(this); this->model = model; + + ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); + QListWidgetItem *item = new QListWidgetItem(); + item->setData(Qt::DisplayRole, "txid"); + item->setData(Qt::UserRole + 1, "displaytext"); + item->setData(Qt::UserRole + 2, "amountbought"); + item->setData(Qt::UserRole + 3, "amountsold"); + item->setData(Qt::UserRole + 4, "status"); + ui->orderHistoryLW->addItem(item); + } void OrderHistoryDialog::setModel(WalletModel *model) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index 644ff68fd4ee1..289dd2917018e 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -53,35 +53,47 @@ painter->setPen(fontPen); } - //GET TITLE, DESCRIPTION AND ICON - QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); - QString title = index.data(Qt::DisplayRole).toString(); - QString description = index.data(Qt::UserRole + 1).toString(); - int imageSpace = 10; - if (!ic.isNull()) { - //ICON - r = option.rect.adjusted(5, 10, -10, -10); - ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 55; - } + // prepare the data for the entry + QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); + QString txid = index.data(Qt::DisplayRole).toString(); + QString displayText = index.data(Qt::UserRole + 1).toString(); + QString amountBought = index.data(Qt::UserRole + 2).toString(); + QString amountSold = index.data(Qt::UserRole + 3).toString(); + QString status = index.data(Qt::UserRole + 4).toString(); - //TITLE - r = option.rect.adjusted(imageSpace, 0, -10, -30); - painter->setFont( QFont( "Lucida Grande", 6, QFont::Normal ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, title, &r); - - //DESCRIPTION - r = option.rect.adjusted(imageSpace, 30, -10, 0); - painter->setFont( QFont( "Lucida Grande", 5, QFont::Normal ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, description, &r); - } + // add the appropriate status icon + int imageSpace = 10; + if (!ic.isNull()) + { + r = option.rect.adjusted(5, 10, -10, -10); + ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); + imageSpace = 55; + } - QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const{ - return QSize(200, 60); // very dumb value - } - - ListDelegate::~ListDelegate() - { + // add the txid + r = option.rect.adjusted(imageSpace, 0, -10, -30); + painter->setFont( QFont( "Lucida Grande", 10, QFont::Bold ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, txid, &r); + // add the displaytext + r = option.rect.adjusted(imageSpace, 30, -10, 0); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayText, &r); + // add the amount bought (green +) + r = option.rect.adjusted(imageSpace, 30, -60, 0); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, amountBought, &r); + // add the amount sold (red -) + r = option.rect.adjusted(imageSpace, 30, -90, 0); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, amountSold, &r); +} - } +QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + return QSize(200, 60); // very dumb value? +} + +ListDelegate::~ListDelegate() +{ +} From 29222063181f4292581538c8d3ef1a2292d2464a Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 18:26:03 -0800 Subject: [PATCH 036/141] Further work for order history --- src/qt/orderhistorydialog.cpp | 68 +++++++++++++++++++-- src/qt/orderlistdelegate.cpp | 108 ++++++++++++++-------------------- 2 files changed, 106 insertions(+), 70 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index feca2bd7532cb..3fd7f4b103463 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -72,14 +72,72 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : this->model = model; ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); + QListWidgetItem *item = new QListWidgetItem(); - item->setData(Qt::DisplayRole, "txid"); - item->setData(Qt::UserRole + 1, "displaytext"); - item->setData(Qt::UserRole + 2, "amountbought"); - item->setData(Qt::UserRole + 3, "amountsold"); - item->setData(Qt::UserRole + 4, "status"); + item->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item->setData(Qt::UserRole + 4, "Awaiting Confirmation"); ui->orderHistoryLW->addItem(item); + QListWidgetItem *item2 = new QListWidgetItem(); + item2->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item2->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item2->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item2->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item2->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item2); + + QListWidgetItem *item3 = new QListWidgetItem(); + item3->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item3->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item3->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item3->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item3->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item3); + + QListWidgetItem *item4 = new QListWidgetItem(); + item4->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item4->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item4->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item4->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item4->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item4); + + QListWidgetItem *item5 = new QListWidgetItem(); + item5->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item5->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item5->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item5->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item5->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item5); + + QListWidgetItem *item6 = new QListWidgetItem(); + item6->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item6->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item6->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item6->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item6->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item6); + + QListWidgetItem *item7 = new QListWidgetItem(); + item7->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item7->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item7->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item7->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item7->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item7); + + QListWidgetItem *item8 = new QListWidgetItem(); + item8->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); + item8->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); + item8->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + item8->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + item8->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(item8); + + } void OrderHistoryDialog::setModel(WalletModel *model) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index 289dd2917018e..e552e094aa771 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -1,65 +1,34 @@ #include "orderlistdelegate.h" - ListDelegate::ListDelegate(QObject *parent) - { - - } - - void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const{ - QRect r = option.rect; - - //Color: #C4C4C4 - QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); - - //Color: #005A83 - QPen lineMarkedPen(QColor::fromRgb(0,90,131), 1, Qt::SolidLine); - - //Color: #333 - QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); - - //Color: #fff - QPen fontMarkedPen(Qt::white, 1, Qt::SolidLine); - - if(option.state & QStyle::State_Selected){ - QLinearGradient gradientSelected(r.left(),r.top(),r.left(),r.height()+r.top()); - gradientSelected.setColorAt(0.0, QColor::fromRgb(119,213,247)); - gradientSelected.setColorAt(0.9, QColor::fromRgb(27,134,183)); - gradientSelected.setColorAt(1.0, QColor::fromRgb(0,120,174)); - painter->setBrush(gradientSelected); - painter->drawRect(r); - - //BORDER - painter->setPen(lineMarkedPen); - painter->drawLine(r.topLeft(),r.topRight()); - painter->drawLine(r.topRight(),r.bottomRight()); - painter->drawLine(r.bottomLeft(),r.bottomRight()); - painter->drawLine(r.topLeft(),r.bottomLeft()); - - painter->setPen(fontMarkedPen); - - } else { - //BACKGROUND - //ALTERNATING COLORS - painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); - painter->drawRect(r); - - //BORDER - painter->setPen(linePen); - painter->drawLine(r.topLeft(),r.topRight()); - painter->drawLine(r.topRight(),r.bottomRight()); - painter->drawLine(r.bottomLeft(),r.bottomRight()); - painter->drawLine(r.topLeft(),r.bottomLeft()); - - painter->setPen(fontPen); - } - - +ListDelegate::ListDelegate(QObject *parent) +{ + +} + +void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + QRect r = option.rect; + QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); + QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); + painter->setPen(linePen); + + // alt the colors + painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); + painter->drawRect(r); + // draw border + painter->setPen(linePen); + painter->drawLine(r.topLeft(),r.topRight()); + painter->drawLine(r.topRight(),r.bottomRight()); + painter->drawLine(r.bottomLeft(),r.bottomRight()); + painter->drawLine(r.topLeft(),r.bottomLeft()); + painter->setPen(fontPen); + // prepare the data for the entry QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); QString txid = index.data(Qt::DisplayRole).toString(); - QString displayText = index.data(Qt::UserRole + 1).toString(); - QString amountBought = index.data(Qt::UserRole + 2).toString(); - QString amountSold = index.data(Qt::UserRole + 3).toString(); + QString displayText = index.data(Qt::UserRole + 4).toString() + ": " + index.data(Qt::UserRole + 1).toString(); + QString amountBought = "+" + index.data(Qt::UserRole + 2).toString(); + QString amountSold = "-" + index.data(Qt::UserRole + 3).toString(); QString status = index.data(Qt::UserRole + 4).toString(); // add the appropriate status icon @@ -71,22 +40,31 @@ imageSpace = 55; } + // setup pens + QPen penBlack(QColor("#000000")); + QPen penRed(QColor("#CC0000")); + QPen penGreen(QColor("#00AA00")); + // add the txid + painter->setPen(penBlack); r = option.rect.adjusted(imageSpace, 0, -10, -30); - painter->setFont( QFont( "Lucida Grande", 10, QFont::Bold ) ); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, txid, &r); - // add the displaytext + // add the displaytext/status r = option.rect.adjusted(imageSpace, 30, -10, 0); painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayText, &r); // add the amount bought (green +) - r = option.rect.adjusted(imageSpace, 30, -60, 0); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, amountBought, &r); + painter->setPen(penGreen); + r = option.rect.adjusted(imageSpace, 0, -10, -30); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); // add the amount sold (red -) - r = option.rect.adjusted(imageSpace, 30, -90, 0); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, amountSold, &r); + painter->setPen(penRed); + r = option.rect.adjusted(imageSpace, 30, -10, 0); + painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); + } QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const From a840262391bc8f4b0a05b84608c7091dfecd9f03 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 20:36:51 -0800 Subject: [PATCH 037/141] more work on order history retrieval --- src/qt/orderhistorydialog.cpp | 205 +++++++++++++++++++++++----------- src/qt/orderlistdelegate.cpp | 11 +- 2 files changed, 147 insertions(+), 69 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 3fd7f4b103463..38e23de9ac4de 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -73,70 +73,147 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); - QListWidgetItem *item = new QListWidgetItem(); - item->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item); - - QListWidgetItem *item2 = new QListWidgetItem(); - item2->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item2->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item2->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item2->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item2->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item2); - - QListWidgetItem *item3 = new QListWidgetItem(); - item3->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item3->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item3->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item3->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item3->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item3); - - QListWidgetItem *item4 = new QListWidgetItem(); - item4->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item4->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item4->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item4->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item4->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item4); - - QListWidgetItem *item5 = new QListWidgetItem(); - item5->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item5->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item5->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item5->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item5->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item5); - - QListWidgetItem *item6 = new QListWidgetItem(); - item6->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item6->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item6->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item6->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item6->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item6); - - QListWidgetItem *item7 = new QListWidgetItem(); - item7->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item7->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item7->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item7->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item7->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item7); - - QListWidgetItem *item8 = new QListWidgetItem(); - item8->setData(Qt::DisplayRole, "6525ca23bb51022086d06d80d91243548d2d1ff546369fcfb187a18fd006df59"); - item8->setData(Qt::UserRole + 1, "Sell 10.12345678 MSC for 12.4566774 SPT #3"); - item8->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - item8->setData(Qt::UserRole + 3, "1234.12345678 MSC"); - item8->setData(Qt::UserRole + 4, "Awaiting Confirmation"); - ui->orderHistoryLW->addItem(item8); - + CWallet *wallet = pwalletMain; + string sAddress = ""; + string addressParam = ""; + bool addressFilter; + + addressFilter = false; + int64_t nCount = 10; + int64_t nFrom = 0; + int64_t nStartBlock = 0; + int64_t nEndBlock = 999999; + + Array response; //prep an array to hold our output + + // rewrite to use original listtransactions methodology from core + LOCK(wallet->cs_wallet); + std::list acentries; + CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); + + // iterate backwards + for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + if (pwtx != 0) + { + uint256 hash = pwtx->GetHash(); + CTransaction wtx; + uint256 blockHash = 0; + if (!GetTransaction(hash, wtx, blockHash, true)) continue; + // get the height of the transaction and check it's within the chosen parameters + blockHash = pwtx->hashBlock; + if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue; + CBlockIndex* pBlockIndex = mapBlockIndex[blockHash]; + if (NULL == pBlockIndex) continue; + int blockHeight = pBlockIndex->nHeight; + if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range + // check if the transaction exists in txlist, and if so is it correct type (21) + if (p_txlistdb->exists(hash)) + { + // get type from levelDB + string strValue; + if (!p_txlistdb->getTX(hash, strValue)) continue; + std::vector vstr; + boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); + if (4 <= vstr.size()) + { + // if tx21, get the details for the list + if(21 == atoi(vstr[2])) + { + unsigned int propertyIdForSale; + unsigned int propertyIdDesired; + uint64_t amountForSale; + uint64_t amountDesired; + string address; + bool divisibleForSale; + bool divisibleDesired; + bool valid; + + CMPMetaDEx temp_metadexoffer; + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity + { + if (0<=mp_obj.step1()) + { + //MPTxType = mp_obj.getTypeString(); + //MPTxTypeInt = mp_obj.getType(); + address = mp_obj.getSender(); + //if (!filterAddress.empty()) if ((senderAddress != filterAddress) && (refAddress != filterAddress)) return -1; // return negative rc if filtering & no match + + int tmpblock=0; + uint32_t tmptype=0; + uint64_t amountNew=0; + valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew); + + if (0 == mp_obj.step2_Value()) + { + propertyIdForSale = mp_obj.getProperty(); + amountForSale = mp_obj.getAmount(); + divisibleForSale = isPropertyDivisible(propertyIdForSale); + if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) + { + propertyIdDesired = temp_metadexoffer.getDesProperty(); + divisibleDesired = isPropertyDivisible(propertyIdDesired); + amountDesired = temp_metadexoffer.getAmountDesired(); + //mdex_action = temp_metadexoffer.getAction(); + } + } + } + } + + // add to list + QListWidgetItem *qItem = new QListWidgetItem(); + qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); + string displayText = "Sell "; + if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } + if(propertyIdForSale < 3) + { + if(propertyIdForSale == 1) displayText += " MSC for "; + if(propertyIdForSale == 2) displayText += " TMSC for "; + } + else + { + displayText += " SPT# for "; + } + if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } + if(propertyIdDesired < 3) + { + if(propertyIdDesired == 1) displayText += " MSC"; + if(propertyIdDesired == 2) displayText += " TMSC"; + } + else + { + displayText += " SPT#"; + } + qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); + qItem->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); + qItem->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + qItem->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + ui->orderHistoryLW->addItem(qItem); + } + } + } + // don't burn time doing more work than we need to +// if ((int)response.size() >= (nCount+nFrom)) break; + } + } + // sort array here and cut on nFrom and nCount +// if (nFrom > (int)response.size()) +// nFrom = response.size(); +// if ((nFrom + nCount) > (int)response.size()) +// nCount = response.size() - nFrom; +// Array::iterator first = response.begin(); +// std::advance(first, nFrom); +// Array::iterator last = response.begin(); +// std::advance(last, nFrom+nCount); + +// if (last != response.end()) response.erase(last, response.end()); +// if (first != response.begin()) response.erase(response.begin(), first); + +// std::reverse(response.begin(), response.end()); // return oldest to newest? + // return response; // return response array for JSON serialization } diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index e552e094aa771..af4f33384e5f6 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -24,7 +24,8 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti painter->setPen(fontPen); // prepare the data for the entry - QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); + QIcon ic = QIcon(":/icons/balances"); +// QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); QString txid = index.data(Qt::DisplayRole).toString(); QString displayText = index.data(Qt::UserRole + 4).toString() + ": " + index.data(Qt::UserRole + 1).toString(); QString amountBought = "+" + index.data(Qt::UserRole + 2).toString(); @@ -48,21 +49,21 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // add the txid painter->setPen(penBlack); r = option.rect.adjusted(imageSpace, 0, -10, -30); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); +// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, txid, &r); // add the displaytext/status r = option.rect.adjusted(imageSpace, 30, -10, 0); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); +// painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayText, &r); // add the amount bought (green +) painter->setPen(penGreen); r = option.rect.adjusted(imageSpace, 0, -10, -30); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); +// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); // add the amount sold (red -) painter->setPen(penRed); r = option.rect.adjusted(imageSpace, 30, -10, 0); - painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); +// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); } From a7fbf54a34ce28df0fc369ea565242e481528b2e Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 10 Nov 2014 23:00:40 -0800 Subject: [PATCH 038/141] Further work on order history for UI --- src/mastercore.cpp | 25 +++++++++++------- src/mastercore.h | 2 +- src/mastercore_dex.cpp | 7 +---- src/mastercore_rpc.cpp | 3 ++- src/qt/metadexdialog.cpp | 1 + src/qt/orderhistorydialog.cpp | 38 +++++++++++++++++++------- src/qt/orderlistdelegate.cpp | 50 ++++++++++++++++++++++------------- 7 files changed, 80 insertions(+), 46 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 9fa07652ed94a..9cf03c4cd4060 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3127,10 +3127,11 @@ unsigned int n_found = 0; } // MPTradeList here -bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalBought) +bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalSold, uint64_t *totalBought) { if (!tdb) return false; - totalBought = 0; + *totalBought = 0; + *totalSold = 0; leveldb::Slice skey, svalue; unsigned int count = 0; std::vector vstr; @@ -3159,11 +3160,12 @@ bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId string address; string address1 = vstr[0]; string address2 = vstr[1]; - unsigned int prop1; - unsigned int prop2; - uint64_t uAmount1; - uint64_t uAmount2; - uint64_t nBought; + unsigned int prop1 = 0; + unsigned int prop2 = 0; + uint64_t uAmount1 = 0; + uint64_t uAmount2 = 0; + uint64_t nBought = 0; + uint64_t nSold = 0; string amountBought; string amountSold; string amount1; @@ -3187,14 +3189,16 @@ bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId address = address2; amountBought = amount2; amountSold = amount1; - nBought = boost::lexical_cast(vstr[5]); + nBought = uAmount2; + nSold = uAmount1; } else { address = address1; amountBought = amount1; amountSold = amount2; - nBought = boost::lexical_cast(vstr[4]); + nBought = uAmount1; + nSold = uAmount2; } int blockNum = atoi(vstr[6]); Object trade; @@ -3205,7 +3209,8 @@ bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId trade.push_back(Pair("amountbought", amountBought)); tradeArray->push_back(trade); ++count; - totalBought=totalBought + nBought; + *totalBought+= nBought; + *totalSold+= nSold; } } } diff --git a/src/mastercore.h b/src/mastercore.h index 6f6a53fb8c938..603f19d366848 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -329,7 +329,7 @@ class CMPTradeList bool exists(const uint256 &txid); void printStats(); void printAll(); - bool getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalBought); + bool getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalSold, uint64_t *totalBought); }; /* leveldb-based storage for the list of ALL Master Protocol TXIDs (key) with validity bit & other misc data as value */ diff --git a/src/mastercore_dex.cpp b/src/mastercore_dex.cpp index 55d29c2ba0524..ff7585ee8ace3 100644 --- a/src/mastercore_dex.cpp +++ b/src/mastercore_dex.cpp @@ -293,13 +293,8 @@ const XDOUBLE desprice = (1/buyersprice); // inverse, to be matched against that if (msc_debug_metadex) fprintf(mp_fp, "==== TRADED !!! %u=%s\n", NewReturn, getTradeReturnType(NewReturn).c_str()); - - // FIXME - // TODO -/* // record the trade in MPTradeList - t_tradelistdb->recordTrade(p_older->getHash(), newo->getHash(), p_older->getAddr(), newo->getAddr(), p_older->getProperty(), newo->getProperty(), buyer_amountGot, paymentAmount, newo->getBlock()); -*/ + t_tradelistdb->recordTrade(p_older->getHash(), newo->getHash(), p_older->getAddr(), newo->getAddr(), p_older->getProperty(), newo->getProperty(), seller_amountGot, buyer_amountGot, newo->getBlock()); diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index eea9256d12034..d88b50223ddb7 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -2143,7 +2143,8 @@ Value gettrade_MP(const Array& params, bool fHelp) // create array of matches Array tradeArray; uint64_t totalBought; - t_tradelistdb->getMatchingTrades(hash, propertyId, &tradeArray, &totalBought); + uint64_t totalSold; + t_tradelistdb->getMatchingTrades(hash, propertyId, &tradeArray, &totalSold, &totalBought); // add array to object txobj.push_back(Pair("matches", tradeArray)); diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index d4cbcca89fac6..cba38e1db0d7b 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -657,6 +657,7 @@ void MetaDExDialog::sendTrade(bool sell) string propDetails = "#" + spNum; string buyStr; string sellStr; + if (!sell) strMsgText += "Your buy will be inverted into a sell offer.\n\n"; strMsgText += "Type: Trade Request\nFrom: " + fromAddress.ToString() + "\n\n"; if (!sell) // clicked buy { diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 38e23de9ac4de..c48186a77443c 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -121,14 +121,17 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : // if tx21, get the details for the list if(21 == atoi(vstr[2])) { - unsigned int propertyIdForSale; - unsigned int propertyIdDesired; - uint64_t amountForSale; - uint64_t amountDesired; + unsigned int propertyIdForSale = 0; + unsigned int propertyIdDesired = 0; + uint64_t amountForSale = 0; + uint64_t amountDesired = 0; string address; bool divisibleForSale; bool divisibleDesired; bool valid; + Array tradeArray; + uint64_t totalBought = 0; + uint64_t totalSold = 0; CMPMetaDEx temp_metadexoffer; CMPTransaction mp_obj; @@ -158,6 +161,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : divisibleDesired = isPropertyDivisible(propertyIdDesired); amountDesired = temp_metadexoffer.getAmountDesired(); //mdex_action = temp_metadexoffer.getAction(); + t_tradelistdb->getMatchingTrades(hash, propertyIdForSale, &tradeArray, &totalSold, &totalBought); } } } @@ -167,30 +171,44 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : QListWidgetItem *qItem = new QListWidgetItem(); qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); string displayText = "Sell "; + string displayIn = "+"; + string displayOut = "-"; + string displayInToken; + string displayOutToken; + if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } if(propertyIdForSale < 3) { - if(propertyIdForSale == 1) displayText += " MSC for "; - if(propertyIdForSale == 2) displayText += " TMSC for "; + if(propertyIdForSale == 1) { displayText += " MSC for "; displayInToken = " MSC"; } + if(propertyIdForSale == 2) { displayText += " TMSC for "; displayInToken = " TMSC"; } } else { displayText += " SPT# for "; + displayInToken = " SPT#"; } if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } if(propertyIdDesired < 3) { - if(propertyIdDesired == 1) displayText += " MSC"; - if(propertyIdDesired == 2) displayText += " TMSC"; + if(propertyIdDesired == 1) { displayText += " MSC"; displayOutToken = " MSC"; } + if(propertyIdDesired == 2) { displayText += " TMSC"; displayOutToken = " TMSC"; } } else { displayText += " SPT#"; + displayOutToken = " SPT#"; } + if(divisibleDesired) { displayIn += FormatDivisibleMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } + if(divisibleForSale) { displayOut += FormatDivisibleMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } + if(totalBought == 0) displayIn = "0"; + if(totalSold == 0) displayOut = "0"; + displayIn += displayInToken; + displayOut += displayOutToken; qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); - qItem->setData(Qt::UserRole + 2, "99999.12345678 SPT #3"); - qItem->setData(Qt::UserRole + 3, "1234.12345678 MSC"); + qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); + qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); qItem->setData(Qt::UserRole + 4, "Awaiting Confirmation"); + qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); ui->orderHistoryLW->addItem(qItem); } } diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index af4f33384e5f6..4ec78ef213205 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -27,10 +27,11 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti QIcon ic = QIcon(":/icons/balances"); // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); QString txid = index.data(Qt::DisplayRole).toString(); - QString displayText = index.data(Qt::UserRole + 4).toString() + ": " + index.data(Qt::UserRole + 1).toString(); - QString amountBought = "+" + index.data(Qt::UserRole + 2).toString(); - QString amountSold = "-" + index.data(Qt::UserRole + 3).toString(); + QString displayText = index.data(Qt::UserRole + 1).toString(); + QString amountBought = index.data(Qt::UserRole + 2).toString(); + QString amountSold = index.data(Qt::UserRole + 3).toString(); QString status = index.data(Qt::UserRole + 4).toString(); + QString senderText = index.data(Qt::UserRole + 5).toString(); // add the appropriate status icon int imageSpace = 10; @@ -38,7 +39,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti { r = option.rect.adjusted(5, 10, -10, -10); ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 55; + imageSpace = 65; } // setup pens @@ -46,31 +47,44 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti QPen penRed(QColor("#CC0000")); QPen penGreen(QColor("#00AA00")); - // add the txid + QFont font = painter->font(); + // add the displaytext painter->setPen(penBlack); + r = option.rect.adjusted(imageSpace, 0, -10, -50); + font.setBold(true); + painter->setFont(font); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); + // add the sender + font.setBold(false); + painter->setFont(font); r = option.rect.adjusted(imageSpace, 0, -10, -30); -// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, senderText, &r); + // add the displaytext + font.setItalic(true); + painter->setFont(font); + r = option.rect.adjusted(imageSpace, 0, -10, -10); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, txid, &r); - // add the displaytext/status - r = option.rect.adjusted(imageSpace, 30, -10, 0); -// painter->setFont( QFont( "Lucida Grande", 8, QFont::Normal ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayText, &r); + // add the status + r = option.rect.adjusted(imageSpace, 0, -10, -50); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, status, &r); // add the amount bought (green +) - painter->setPen(penGreen); + font.setItalic(false); + font.setBold(true); + painter->setFont(font); + if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); r = option.rect.adjusted(imageSpace, 0, -10, -30); -// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); // add the amount sold (red -) - painter->setPen(penRed); - r = option.rect.adjusted(imageSpace, 30, -10, 0); -// painter->setFont( QFont( "Lucida Grande", 8, QFont::Bold ) ); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); - + if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); + r = option.rect.adjusted(imageSpace, 0, -10, -10); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountSold, &r); + font.setBold(false); + painter->setFont(font); } QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const { - return QSize(200, 60); // very dumb value? + return QSize(200, 75); // very dumb value? } ListDelegate::~ListDelegate() From 6ccf490e47e96d5e551b569c1bb156f11d797b6e Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 11 Nov 2014 12:45:00 -0800 Subject: [PATCH 039/141] icons for metadex order history --- src/qt/Makefile.am | 6 ++++++ src/qt/bitcoin.qrc | 6 ++++++ src/qt/res/icons/mp_meta_cancelled.png | Bin 0 -> 5295 bytes src/qt/res/icons/mp_meta_filled.png | Bin 0 -> 1492 bytes src/qt/res/icons/mp_meta_open.png | Bin 0 -> 2952 bytes src/qt/res/icons/mp_meta_partial.png | Bin 0 -> 2603 bytes src/qt/res/icons/mp_meta_partialclosed.png | Bin 0 -> 3006 bytes src/qt/res/icons/mp_meta_pending.png | Bin 0 -> 2722 bytes 8 files changed, 12 insertions(+) create mode 100644 src/qt/res/icons/mp_meta_cancelled.png create mode 100644 src/qt/res/icons/mp_meta_filled.png create mode 100644 src/qt/res/icons/mp_meta_open.png create mode 100644 src/qt/res/icons/mp_meta_partial.png create mode 100644 src/qt/res/icons/mp_meta_partialclosed.png create mode 100644 src/qt/res/icons/mp_meta_pending.png diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 0333b1aa39ed3..48f8a0efac43b 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -240,6 +240,12 @@ RES_ICONS = \ res/icons/mp_home.png \ res/icons/mp_receive.png \ res/icons/mp_send.png \ + res/icons/mp_meta_cancelled.png \ + res/icons/mp_meta_filled.png \ + res/icons/mp_meta_open.png \ + res/icons/mp_meta_partialclosed.png \ + res/icons/mp_meta_partial.png \ + res/icons/mp_meta_pending.png \ res/icons/add.png \ res/icons/address-book.png \ res/icons/bitcoin.ico \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 12174de1dd553..17aeab3a42046 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,5 +1,11 @@ + res/icons/mp_meta_cancelled.png + res/icons/mp_meta_filled.png + res/icons/mp_meta_open.png + res/icons/mp_meta_partialclosed.png + res/icons/mp_meta_partial.png + res/icons/mp_meta_pending.png res/icons/mp_balances.png res/icons/mp_toolbox.png res/icons/mp_exchange.png diff --git a/src/qt/res/icons/mp_meta_cancelled.png b/src/qt/res/icons/mp_meta_cancelled.png new file mode 100644 index 0000000000000000000000000000000000000000..837ddec05929eceef57c62c53fac9dd28d5400d0 GIT binary patch literal 5295 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 literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/mp_meta_pending.png b/src/qt/res/icons/mp_meta_pending.png new file mode 100644 index 0000000000000000000000000000000000000000..1d49d27d7ecae51bf270faa92ec00c162513da4f GIT binary patch literal 2722 zcmV;T3SISyP)1I8O6Hj zqD*mYFc1I^8cz1HijD*qsqUuGd_0 zTm>l{LKF-Ek{{tc_>luo!9ap3=g6z35SC(~@2Qe>ss?o!SA`4~ao}ChdlXgJJjmb> zA#Vr}9(2U;KIa(V$(#-bB^YszF^3FgLx9@A4|3o$OiwFwA`DX@f@OejY$8}GgOAug zq>%?Yd+;Agn(XAKUiT8W2)y56{8Yd;qrb6Lpq2vknbEJE3iL%GfEoQ7sz4|L@Veh*{u)*U9NRzz*kkUMwzdY_ zb*n}{Mn0(xnee!@R+GqYzyHDZ9r!F&|Gqu0N-+*tX;W&Gq4&sG}xC23EVdJpb8|&=hP*DV{TI) z{cactil>+>05CF15OxiNyZD2+tsp=rb#EsozYkTG$s$3N1uS8FC19P^1R&q;jS+R@ z_MKEn5Cwers7R-C1@k6e6CPB-4rR94ma8UBv{TW&T@2z=E2r$)wNUo#=w z(9+sI4h6_EMGU3Y+4B>jx@koyK@{+#_(sUGHdAcR-YAPI0o?gBhwGXyj`Cjk0-qFI z-_QjDG^^${ZglR*P^cST&+6kS>Jh~kg4W#R#DRlM!3GeFI>h)eIl&X_*H=~`&(6)W z^5UOD!N{AJ~Hc%6I=pA;GSWS3O5Keuuv`5csf+%``EW1YsV*dIA0VE87C4ALrHx{N)h9 zbRz*)-};$Xk73Z}R5+(@;A=+!*Uny;@Ku5>&u;Sg-A3P$k8|p1S`q-}xA}tCoPeMF zOWw%A5P*U;+BS9C695}eQaqO-Kmvw#Es;Bp;#@&3V5-_Woj%OcOkSUq?PgIrB2hdw zJZ8#3s^DX)SLR;BNwl4%L4dL@;3tvD$!t4I!O9>&(SYBuBq-Vj{Kh7MvI>9=CDYz! z-X(#;n_E^CU{N)%apQ+h%NTeY;6XFGZh1S^)$ospRqgz3-A7 zZSV=cDP|>`Zx^CODTrtGIE;T{N-6{ZfmAbchAfv*K zb-w{k0lQjFfP%TH4M*0(G69@eK$-wy`t_(0mU=GWVs5Wy1l18G(!8GLiGIRIT(Oq1 zt|q_~MNcuyCbH~9Tlc;LC)fNQzZ1E<3qBK8ttl@8-AItHmVYk=AQ=YgDf5-H7i464jA4Mza}U9-xlK$sd|e136DsnK8S`-Am%kL;^WWuUF|8i2$4g(@fHqvT3gF(Y$IYIN|!Iel8bQ`dw>^ zdWHG9nPN+8JN6geA;M#Py~^@eyI4%+rPhIljQ{?^!^#Zexv@*4D}Z4K{L@k2WYv2$ zr!<^pitjY8S=`@V&l}_H5P}-BWbS?HR^nK&LmxU*V#-b;EeslfOLO@k0Kp4PG zVaDK*IQTmq@MD$cmIzNc31$r@iQ4wK;K$7Ys>1;s={J}pX8j_-7p4Fv9H=Gx(g%w$nKD{}Cql-rhU?;RoxIWL0-$GQyDyE&N` zXp;R2=I3TEx3sqZ!j?LUHW*Ap$NP`!ncF9)098tmWlOzk^nWx&`qd}L>V`w z3g}7`z=IH7oCuv<9b_kvWj@NW-+qDmPV3qepoT(ZIVqZ}LPivFxFEZdzQ{*;NwpCk cWd92=08$QThDXZx)c^nh07*qoM6N<$f_)bfQ2+n{ literal 0 HcmV?d00001 From ae2d2af8b52f1bbf24f96a701d468a1ac4b47781 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 11 Nov 2014 13:25:06 -0800 Subject: [PATCH 040/141] Broken --- src/qt/metadexdialog.cpp | 1 + src/qt/orderhistorydialog.cpp | 15 ++++++++------- src/qt/orderlistdelegate.cpp | 5 ++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index cba38e1db0d7b..e4b9bf9724a03 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -66,6 +66,7 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui(new Ui::MetaDExDialog), model(0) { +printf("hereme\n"); ui->setupUi(this); this->model = model; diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index d14f2a7df4aae..b4b7c326340b1 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -68,9 +68,9 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui(new Ui::orderHistoryDialog), model(0) { +printf("here\n"); ui->setupUi(this); this->model = model; - ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); CWallet *wallet = pwalletMain; @@ -193,6 +193,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : bool filled = false; if(totalSold>0) partialFilled = true; if(totalSold>=amountForSale) filled = true; + statusText = "Unknown (error?)"; if((!orderOpen) && (filled)) statusText = "Closed / Filled"; if((orderOpen) && (!partialFilled)) statusText = "Open"; if((orderOpen) && (partialFilled)) statusText = "Open / Partially Filled"; @@ -209,26 +210,26 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } if(propertyIdForSale < 3) { - if(propertyIdForSale == 1) { displayText += " MSC for "; displayInToken = " MSC"; } - if(propertyIdForSale == 2) { displayText += " TMSC for "; displayInToken = " TMSC"; } + if(propertyIdForSale == 1) { displayText += " MSC for "; displayOutToken = " MSC"; } + if(propertyIdForSale == 2) { displayText += " TMSC for "; displayOutToken = " TMSC"; } } else { string s = to_string(propertyIdForSale); displayText += " SPT#" + s + " for "; - displayInToken = " SPT#" + s; + displayOutToken = " SPT#" + s; } if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } if(propertyIdDesired < 3) { - if(propertyIdDesired == 1) { displayText += " MSC"; displayOutToken = " MSC"; } - if(propertyIdDesired == 2) { displayText += " TMSC"; displayOutToken = " TMSC"; } + if(propertyIdDesired == 1) { displayText += " MSC"; displayInToken = " MSC"; } + if(propertyIdDesired == 2) { displayText += " TMSC"; displayInToken = " TMSC"; } } else { string s = to_string(propertyIdDesired); displayText += " SPT#" + s; - displayOutToken = " SPT#" + s; + displayInToken = " SPT#" + s; } if(divisibleDesired) { displayIn += FormatDivisibleMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } if(divisibleForSale) { displayOut += FormatDivisibleMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index 941608c33b409..ce6c618f10654 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -24,7 +24,6 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti painter->setPen(fontPen); // prepare the data for the entry - QIcon ic = QIcon(":/icons/balances"); // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); QString txidstatus = index.data(Qt::UserRole + 4).toString() + " (" + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,8)) + "...)"; @@ -37,6 +36,10 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // add the appropriate status icon int imageSpace = 10; + QIcon ic = QIcon(":/icons/meta_cancelled"); + if(status == "Closed / Filled") ic = QIcon(":/icons/meta_filled"); + if(status == "Open") ic = QIcon(":/icons/meta_open"); + if(status == "Open / Partially Filled") ic = QIcon(":/icons/meta_partial"); if (!ic.isNull()) { r = option.rect.adjusted(5, 10, -10, -10); From 3313de97dbc057cdfc137c5f8bafdf2109acbaa1 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 11 Nov 2014 13:55:23 -0800 Subject: [PATCH 041/141] Commit before branch retest --- src/qt/orderhistorydialog.cpp | 4 ++-- src/qt/orderlistdelegate.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index b4b7c326340b1..bd01fcbf2ae9e 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -68,7 +68,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui(new Ui::orderHistoryDialog), model(0) { -printf("here\n"); +/*printf("here\n"); ui->setupUi(this); this->model = model; ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); @@ -265,7 +265,7 @@ printf("here\n"); // std::reverse(response.begin(), response.end()); // return oldest to newest? // return response; // return response array for JSON serialization - +*/ } void OrderHistoryDialog::setModel(WalletModel *model) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index ce6c618f10654..278f5504f6c58 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -7,7 +7,7 @@ ListDelegate::ListDelegate(QObject *parent) void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { - QRect r = option.rect; +/* QRect r = option.rect; QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); painter->setPen(linePen); @@ -74,6 +74,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); font.setBold(false); painter->setFont(font); +*/ } QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const From e99e093723b232ccee32f45b0ad0b183992370c0 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 11 Nov 2014 19:57:57 -0800 Subject: [PATCH 042/141] More order history changes --- src/mastercore_dex.cpp | 2 +- src/qt/orderhistorydialog.cpp | 14 +++++++----- src/qt/orderlistdelegate.cpp | 43 +++++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/mastercore_dex.cpp b/src/mastercore_dex.cpp index f2815e3348d52..cfdfbc8e7c337 100644 --- a/src/mastercore_dex.cpp +++ b/src/mastercore_dex.cpp @@ -294,7 +294,7 @@ const XDOUBLE desprice = (1/buyersprice); // inverse, to be matched against that if (msc_debug_metadex) fprintf(mp_fp, "==== TRADED !!! %u=%s\n", NewReturn, getTradeReturnType(NewReturn).c_str()); // record the trade in MPTradeList - t_tradelistdb->recordTrade(p_older->getHash(), newo->getHash(), p_older->getAddr(), newo->getAddr(), p_older->getProperty(), newo->getProperty(), seller_amountGot, buyer_amountGot, newo->getBlock()); + t_tradelistdb->recordTrade(p_older->getHash(), newo->getHash(), p_older->getAddr(), newo->getAddr(), p_older->getDesProperty(), newo->getDesProperty(), seller_amountGot, buyer_amountGot, newo->getBlock()); if (msc_debug_metadex) fprintf(mp_fp, "++ erased old: %s\n", iitt->ToString().c_str()); // erase the old seller element diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index bd01fcbf2ae9e..1de9fbe9a0b3c 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -68,7 +68,6 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui(new Ui::orderHistoryDialog), model(0) { -/*printf("here\n"); ui->setupUi(this); this->model = model; ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); @@ -193,10 +192,12 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : bool filled = false; if(totalSold>0) partialFilled = true; if(totalSold>=amountForSale) filled = true; - statusText = "Unknown (error?)"; - if((!orderOpen) && (filled)) statusText = "Closed / Filled"; - if((orderOpen) && (!partialFilled)) statusText = "Open"; - if((orderOpen) && (partialFilled)) statusText = "Open / Partially Filled"; + statusText = "UNKNOWN"; + if((!orderOpen) && (!partialFilled)) statusText = "CANCELLED"; + if((!orderOpen) && (partialFilled)) statusText = "PART CANCEL"; + if((!orderOpen) && (filled)) statusText = "FILLED"; + if((orderOpen) && (!partialFilled)) statusText = "OPEN"; + if((orderOpen) && (partialFilled)) statusText = "PART FILLED"; // add to list QListWidgetItem *qItem = new QListWidgetItem(); @@ -237,6 +238,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : if(totalSold == 0) displayOut = "0"; displayIn += displayInToken; displayOut += displayOutToken; +printf("displayIn %s displayOut %s\n",displayIn.c_str(),displayOut.c_str()); qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); @@ -265,7 +267,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : // std::reverse(response.begin(), response.end()); // return oldest to newest? // return response; // return response array for JSON serialization -*/ + } void OrderHistoryDialog::setModel(WalletModel *model) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index 278f5504f6c58..caf1827dd13bc 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -7,7 +7,7 @@ ListDelegate::ListDelegate(QObject *parent) void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { -/* QRect r = option.rect; + QRect r = option.rect; QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); painter->setPen(linePen); @@ -26,7 +26,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // prepare the data for the entry // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidstatus = index.data(Qt::UserRole + 4).toString() + " (" + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,8)) + "...)"; + QString txidsender = index.data(Qt::UserRole + 5).toString() + " (" + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,16)) + "...)"; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); QString displayText = index.data(Qt::UserRole + 1).toString(); QString amountBought = index.data(Qt::UserRole + 2).toString(); @@ -37,14 +37,16 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // add the appropriate status icon int imageSpace = 10; QIcon ic = QIcon(":/icons/meta_cancelled"); - if(status == "Closed / Filled") ic = QIcon(":/icons/meta_filled"); - if(status == "Open") ic = QIcon(":/icons/meta_open"); - if(status == "Open / Partially Filled") ic = QIcon(":/icons/meta_partial"); + if(status == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); + if(status == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); + if(status == "FILLED") ic = QIcon(":/icons/meta_filled"); + if(status == "OPEN") ic = QIcon(":/icons/meta_open"); + if(status == "PART FILLED") ic = QIcon(":/icons/meta_partial"); if (!ic.isNull()) { - r = option.rect.adjusted(5, 10, -10, -10); + r = option.rect.adjusted(100, 10, -10, -10); ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 55; + imageSpace = 145; } // setup pens @@ -53,33 +55,44 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti QPen penGreen(QColor("#00AA00")); QFont font = painter->font(); + painter->setPen(penBlack); + // add the status + font.setItalic(true); + painter->setFont(font); + r = option.rect.adjusted(5, 0, -10, -25); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); + // add the datetime + font.setItalic(false); + painter->setFont(font); + r = option.rect.adjusted(5, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, "01/01 12:12", &r); // add the displaytext painter->setPen(penBlack); - r = option.rect.adjusted(imageSpace, 0, -10, -30); + r = option.rect.adjusted(imageSpace, 0, -10, -25); font.setBold(true); painter->setFont(font); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); - // add the txid/status + // add the txid/sender font.setBold(false); painter->setFont(font); - r = option.rect.adjusted(imageSpace, 30, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidstatus, &r); + r = option.rect.adjusted(imageSpace, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidsender, &r); font.setBold(true); painter->setFont(font); if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); - r = option.rect.adjusted(imageSpace, 0, -10, -30); + r = option.rect.adjusted(imageSpace, 0, -10, -25); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); - r = option.rect.adjusted(imageSpace, 30, -10, 0); + r = option.rect.adjusted(imageSpace, 25, -10, 0); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); font.setBold(false); painter->setFont(font); -*/ + } QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const { - return QSize(200, 60); // very dumb value? + return QSize(200, 50); // very dumb value? } ListDelegate::~ListDelegate() From 8db5b45883acb6c3f57416e1986f6eea27143e6c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 11 Nov 2014 20:46:06 -0800 Subject: [PATCH 043/141] More working order history --- src/qt/orderhistorydialog.cpp | 7 ++++++- src/qt/orderlistdelegate.cpp | 29 +++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 1de9fbe9a0b3c..fd2279ca17ee1 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -100,6 +100,8 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : CTransaction wtx; uint256 blockHash = 0; if (!GetTransaction(hash, wtx, blockHash, true)) continue; + // get the time of the tx + int64_t nTime = pwtx->GetTxTime(); // get the height of the transaction and check it's within the chosen parameters blockHash = pwtx->hashBlock; if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue; @@ -238,12 +240,15 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : if(totalSold == 0) displayOut = "0"; displayIn += displayInToken; displayOut += displayOutToken; -printf("displayIn %s displayOut %s\n",displayIn.c_str(),displayOut.c_str()); + QDateTime txTime; + txTime.setTime_t(nTime); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); qItem->setData(Qt::UserRole + 4, QString::fromStdString(statusText)); qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); + qItem->setData(Qt::UserRole + 6, txTimeStr); ui->orderHistoryLW->addItem(qItem); } } diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index caf1827dd13bc..051f9cf7bfffc 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -26,13 +26,15 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // prepare the data for the entry // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = index.data(Qt::UserRole + 5).toString() + " (" + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,16)) + "...)"; + QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,16)) + "..."; + txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,16)) + "...)"; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); QString displayText = index.data(Qt::UserRole + 1).toString(); QString amountBought = index.data(Qt::UserRole + 2).toString(); QString amountSold = index.data(Qt::UserRole + 3).toString(); QString status = index.data(Qt::UserRole + 4).toString(); QString senderText = index.data(Qt::UserRole + 5).toString(); + QString txTimeText = index.data(Qt::UserRole + 6).toString(); // add the appropriate status icon int imageSpace = 10; @@ -44,46 +46,49 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti if(status == "PART FILLED") ic = QIcon(":/icons/meta_partial"); if (!ic.isNull()) { - r = option.rect.adjusted(100, 10, -10, -10); + r = option.rect.adjusted(5, 10, -10, -10); ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 145; + imageSpace = 60; } // setup pens QPen penBlack(QColor("#000000")); QPen penRed(QColor("#CC0000")); QPen penGreen(QColor("#00AA00")); + QPen penGrey(QColor("#606060")); QFont font = painter->font(); painter->setPen(penBlack); // add the status - font.setItalic(true); + font.setItalic(false); painter->setFont(font); - r = option.rect.adjusted(5, 0, -10, -25); + r = option.rect.adjusted(imageSpace-19, 0, -10, -25); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); // add the datetime - font.setItalic(false); + font.setItalic(true); painter->setFont(font); - r = option.rect.adjusted(5, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, "01/01 12:12", &r); + r = option.rect.adjusted(imageSpace-19, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txTimeText, &r); // add the displaytext painter->setPen(penBlack); - r = option.rect.adjusted(imageSpace, 0, -10, -25); + r = option.rect.adjusted(imageSpace+115, 0, -10, -25); font.setBold(true); + font.setItalic(false); painter->setFont(font); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); // add the txid/sender + painter->setPen(penGrey); font.setBold(false); painter->setFont(font); - r = option.rect.adjusted(imageSpace, 25, -10, 0); + r = option.rect.adjusted(imageSpace+115, 25, -10, 0); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidsender, &r); font.setBold(true); painter->setFont(font); if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); - r = option.rect.adjusted(imageSpace, 0, -10, -25); + r = option.rect.adjusted(imageSpace+115, 0, -10, -25); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); - r = option.rect.adjusted(imageSpace, 25, -10, 0); + r = option.rect.adjusted(imageSpace+115, 25, -10, 0); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); font.setBold(false); painter->setFont(font); From 6eaf893087a979e83e3a42098c4102dc7a813879 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 13 Nov 2014 12:27:48 -0800 Subject: [PATCH 044/141] Minor formatting changes --- src/qt/orderlistdelegate.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index 051f9cf7bfffc..bf74e12573a5c 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -26,8 +26,8 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // prepare the data for the entry // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,16)) + "..."; - txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,16)) + "...)"; + QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; + txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); QString displayText = index.data(Qt::UserRole + 1).toString(); QString amountBought = index.data(Qt::UserRole + 2).toString(); @@ -65,6 +65,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti r = option.rect.adjusted(imageSpace-19, 0, -10, -25); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); // add the datetime + painter->setPen(penGrey); font.setItalic(true); painter->setFont(font); r = option.rect.adjusted(imageSpace-19, 25, -10, 0); From 55980ff1bf92ad8bb3ca91dcc27a726a97991826 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Wed, 26 Nov 2014 19:50:06 -0800 Subject: [PATCH 045/141] Fix broken alerts --- src/mastercore.cpp | 3 +-- src/qt/metadexdialog.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 26caf298500bd..a1a7dcfec082e 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -4095,7 +4095,7 @@ std::string new_global_alert_message; case MASTERCORE_MESSAGE_TYPE_ALERT: // check the packet version is also FF - if ((int)version != 65535) + if ((int)version == 65535) { rc = step2_Alert(&new_global_alert_message); if (rc == 0) global_alert_message = new_global_alert_message; @@ -4104,7 +4104,6 @@ std::string new_global_alert_message; break; default: - return (PKT_ERROR -100); } diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index e4b9bf9724a03..2f800f0f47976 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -236,7 +236,7 @@ void MetaDExDialog::UpdateSellOffers() if ( ((testeco) && (obj.getDesProperty() == 2)) || ((!testeco) && (obj.getDesProperty() == 1)) ) { available += obj.getAmountDesired(); - total += obj.getAmount(); + total += obj.getAmountForSale(); if(IsMyAddress(obj.getAddr())) includesMe = true; } } @@ -297,7 +297,7 @@ void MetaDExDialog::UpdateBuyOffers() if(obj.getDesProperty()==global_metadex_market) { available += obj.getAmountDesired(); - total += obj.getAmount(); + total += obj.getAmountForSale(); if(IsMyAddress(obj.getAddr())) includesMe = true; } } From f80852415d59e1e02316d81e59863facea727820 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Wed, 26 Nov 2014 22:58:29 -0800 Subject: [PATCH 046/141] Add address search to toolbox --- src/qt/Makefile.am | 4 + src/qt/forms/lookupaddressdialog.ui | 515 ++++++++++++++++++++++++++++ src/qt/lookupaddressdialog.cpp | 183 ++++++++++ src/qt/lookupaddressdialog.h | 49 +++ src/qt/overviewpage.cpp | 11 +- src/qt/walletview.cpp | 11 + src/qt/walletview.h | 2 + 7 files changed, 770 insertions(+), 5 deletions(-) create mode 100644 src/qt/forms/lookupaddressdialog.ui create mode 100644 src/qt/lookupaddressdialog.cpp create mode 100644 src/qt/lookupaddressdialog.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 48f8a0efac43b..fc734ceb468dc 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -104,6 +104,7 @@ QT_FORMS_UI = \ forms/orderhistorydialog.ui \ forms/metadexdialog.ui \ forms/lookupspdialog.ui \ + forms/lookupaddressdialog.ui \ forms/signverifymessagedialog.ui \ forms/transactiondescdialog.ui @@ -144,6 +145,7 @@ QT_MOC_CPP = \ moc_orderhistorydialog.cpp \ moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ + moc_lookupaddressdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ moc_trafficgraphwidget.cpp \ @@ -213,6 +215,7 @@ BITCOIN_QT_H = \ metadexdialog.h \ orderhistorydialog.h \ lookupspdialog.h \ + lookupaddressdialog.h \ orderlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ @@ -334,6 +337,7 @@ BITCOIN_QT_CPP += \ orderhistorydialog.cpp \ orderlistdelegate.cpp \ lookupspdialog.cpp \ + lookupaddressdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ transactiondescdialog.cpp \ diff --git a/src/qt/forms/lookupaddressdialog.ui b/src/qt/forms/lookupaddressdialog.ui new file mode 100644 index 0000000000000..ffbf8fc37b72a --- /dev/null +++ b/src/qt/forms/lookupaddressdialog.ui @@ -0,0 +1,515 @@ + + + LookupAddressDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + true + + + + 0 + 0 + + + + Search Address: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + + + Search + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + 75 + true + + + + Address Information + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 0 + + + + + Address: + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Type: + + + + + + + + 50 + false + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 12 + + + + + + + + + + <b>Balance Information</b> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + + + Property1: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property2: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property3: + + + + + + + + 75 + true + + + + Qt::LeftToRight + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property4: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property5: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property6: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property7: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property8: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property9: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Property10: + + + + + + + + 75 + true + + + + 0.00 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + *Only first 10 properties shown + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + + diff --git a/src/qt/lookupaddressdialog.cpp b/src/qt/lookupaddressdialog.cpp new file mode 100644 index 0000000000000..f728ca67dbf5f --- /dev/null +++ b/src/qt/lookupaddressdialog.cpp @@ -0,0 +1,183 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "lookupaddressdialog.h" +#include "ui_lookupaddressdialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +using namespace json_spirit; +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" + +#include +#include +#include + +LookupAddressDialog::LookupAddressDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LookupAddressDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; + + // populate placeholder text + ui->searchLineEdit->setPlaceholderText("Search address"); + + // connect actions + connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); +} + +void LookupAddressDialog::searchAddress() +{ + // search function to lookup address + string searchText = ui->searchLineEdit->text().toStdString(); + + // first let's check if we have a searchText, if not do nothing + if (searchText.empty()) return; + + // lets see if the string is a valid bitcoin address + CBitcoinAddress address; + address.SetString(searchText); // no null check on searchText required we've already checked it's not empty above + if (address.IsValid()) //do what? + { + // update top fields + ui->addressLabel->setText(QString::fromStdString(searchText)); + if ((searchText.substr(0,1) == "1") || (searchText.substr(0,1) == "m") || (searchText.substr(0,1) == "n")) ui->addressTypeLabel->setText("Public Key Hash"); + if ((searchText.substr(0,1) == "2") || (searchText.substr(0,1) == "3")) ui->addressTypeLabel->setText("Pay to Script Hash"); + + //scrappy way to do this, find a more efficient way of interacting with labels + //show first 10 SPs with balances - needs to be converted to listwidget or something + unsigned int propertyId; + unsigned int lastFoundPropertyIdMainEco = 0; + unsigned int lastFoundPropertyIdTestEco = 0; + string pName[12]; + uint64_t pBal[12]; + bool pDivisible[12]; + bool pFound[12]; + unsigned int pItem; + bool foundProperty = false; + for (pItem = 1; pItem < 12; pItem++) + { + pFound[pItem] = false; + for (propertyId = lastFoundPropertyIdMainEco+1; propertyId<100000; propertyId++) + { + foundProperty=false; + if (getUserAvailableMPbalance(searchText, propertyId) > 0) + { + lastFoundPropertyIdMainEco = propertyId; + foundProperty=true; + pName[pItem] = getPropertyName(propertyId).c_str(); + if(pName[pItem].size()>22) pName[pItem]=pName[pItem].substr(0,22)+"..."; + pName[pItem] += " (#" + static_cast( &(ostringstream() << propertyId) )->str() + ")"; + pBal[pItem] = getUserAvailableMPbalance(searchText, propertyId); + pDivisible[pItem] = isPropertyDivisible(propertyId); + pFound[pItem] = true; + break; + } + } + + // have we found a property in main eco? If not let's try test eco + if (!foundProperty) + { + for (propertyId = lastFoundPropertyIdTestEco+1; propertyId<100000; propertyId++) + { + if (getUserAvailableMPbalance(searchText, propertyId+2147483647) > 0) + { + lastFoundPropertyIdTestEco = propertyId; + foundProperty=true; + pName[pItem] = getPropertyName(propertyId+2147483647).c_str(); + if(pName[pItem].size()>22) pName[pItem]=pName[pItem].substr(0,22)+"..."; + pName[pItem] += " (#" + static_cast( &(ostringstream() << propertyId+2147483647) )->str() + ")"; + pBal[pItem] = getUserAvailableMPbalance(searchText, propertyId+2147483647); + pDivisible[pItem] = isPropertyDivisible(propertyId+2147483647); + pFound[pItem] = true; + break; + } + } + } + } + + // set balance info + QLabel* balances[] = { ui->propertyLabel1, ui->propertyLabel2, ui->propertyLabel3, ui->propertyLabel4, ui->propertyLabel5, ui->propertyLabel6, ui->propertyLabel7, ui->propertyLabel8, ui->propertyLabel9, ui->propertyLabel10 }; + QLabel* labels[] = { ui->property1, ui->property2, ui->property3, ui->property4, ui->property5, ui->property6, ui->property7, ui->property8, ui->property9, ui->property10 }; + for (pItem = 1; pItem < 11; pItem++) + { + if (pFound[pItem]) + { + labels[pItem-1]->setVisible(true); + balances[pItem-1]->setVisible(true); + labels[pItem-1]->setText(pName[pItem].c_str()); + string tokenLabel = " SPT"; + if (pName[pItem]=="Test MasterCoin (#2)") { tokenLabel = " TMSC"; } + if (pName[pItem]=="MasterCoin (#1)") { tokenLabel = " MSC"; } + if (pDivisible[pItem]) + { + balances[pItem-1]->setText(QString::fromStdString(FormatDivisibleMP(pBal[pItem]) + tokenLabel)); + } + else + { + string balText = static_cast( &(ostringstream() << pBal[pItem]) )->str(); + balText += tokenLabel; + balances[pItem-1]->setText(balText.c_str()); + } + } + else + { + labels[pItem-1]->setVisible(false); + balances[pItem-1]->setVisible(false); + } + } + } +} + +void LookupAddressDialog::searchButtonClicked() +{ + searchAddress(); +} diff --git a/src/qt/lookupaddressdialog.h b/src/qt/lookupaddressdialog.h new file mode 100644 index 0000000000000..8fa9711de4740 --- /dev/null +++ b/src/qt/lookupaddressdialog.h @@ -0,0 +1,49 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef LOOKUPADDRESSDIALOG_H +#define LOOKUPADDRESSDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class LookupAddressDialog; +} + +/** Dialog for looking up Master Protocol address */ +class LookupAddressDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LookupAddressDialog(QWidget *parent = 0); + void searchAddress(); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + +public slots: + void searchButtonClicked(); + +private: + Ui::LookupAddressDialog *ui; + WalletModel *model; + +//private slots: + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // LOOKUPADDRESSDIALOG_H diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 746f4ea8a270e..5993eb28ebd43 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -211,7 +211,8 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 //scrappy way to do this, find a more efficient way of interacting with labels //show first 5 SPs with balances - needs to be converted to listwidget or something unsigned int propertyId; - unsigned int lastFoundPropertyId = 1; + unsigned int lastFoundPropertyIdMainEco = 1; + unsigned int lastFoundPropertyIdTestEco = 1; string spName[7]; uint64_t spBal[7]; bool spDivisible[7]; @@ -222,12 +223,12 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 for (spItem = 1; spItem < 7; spItem++) { spFound[spItem] = false; - for (propertyId = lastFoundPropertyId+1; propertyId<100000; propertyId++) + for (propertyId = lastFoundPropertyIdMainEco+1; propertyId<100000; propertyId++) { foundProperty=false; if ((global_balance_money_maineco[propertyId] > 0) || (global_balance_reserved_maineco[propertyId] > 0)) { - lastFoundPropertyId = propertyId; + lastFoundPropertyIdMainEco = propertyId; foundProperty=true; spName[spItem] = getPropertyName(propertyId).c_str(); if(spName[spItem].size()>22) spName[spItem]=spName[spItem].substr(0,22)+"..."; @@ -241,11 +242,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 // have we found a property in main eco? If not let's try test eco if (!foundProperty) { - for (propertyId = lastFoundPropertyId+1; propertyId<100000; propertyId++) + for (propertyId = lastFoundPropertyIdTestEco+1; propertyId<100000; propertyId++) { if ((global_balance_money_testeco[propertyId] > 0) || (global_balance_reserved_testeco[propertyId] > 0)) { - lastFoundPropertyId = propertyId; + lastFoundPropertyIdTestEco = propertyId; foundProperty=true; spName[spItem] = getPropertyName(propertyId+2147483647).c_str(); if(spName[spItem].size()>22) spName[spItem]=spName[spItem].substr(0,22)+"..."; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 61ac3221cc8b8..c96c0e82fc3e4 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -15,6 +15,7 @@ #include "sendcoinsdialog.h" #include "sendmpdialog.h" #include "lookupspdialog.h" +#include "lookupaddressdialog.h" #include "metadexdialog.h" #include "signverifymessagedialog.h" #include "transactiontablemodel.h" @@ -131,6 +132,16 @@ WalletView::WalletView(QWidget *parent): // toolbox page toolboxPage = new QWidget(this); + QVBoxLayout *tvbox = new QVBoxLayout(); + addressLookupTab = new LookupAddressDialog(); +// txLookupTab = new LookupTXDialog(); + QTabWidget *tTabHolder = new QTabWidget(); + tTabHolder->addTab(addressLookupTab,tr("Search Address")); +// tTabHolder->addTab(txLookupTab,tr("Search Transaction"); + tTabHolder->addTab(new QWidget(),tr("Search Transaction")); + + tvbox->addWidget(tTabHolder); + toolboxPage->setLayout(tvbox); // add pages addWidget(overviewPage); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 5769ab63f38bb..3a228bf4e900e 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -15,6 +15,7 @@ class SendCoinsDialog; class SendMPDialog; class OrderHistoryDialog; class LookupSPDialog; +class LookupAddressDialog; class MetaDExDialog; class SendCoinsRecipient; class TransactionView; @@ -72,6 +73,7 @@ class WalletView : public QStackedWidget SendCoinsDialog *sendCoinsTab; SendMPDialog *sendMPTab; LookupSPDialog *spLookupTab; + LookupAddressDialog *addressLookupTab; OrderHistoryDialog *orderHistoryTab; MetaDExDialog *metaDExTab; TransactionView *transactionView; From b84ae1a442ad2033981a8072eb5a60fd4390417c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 12:54:58 -0800 Subject: [PATCH 047/141] Updates to toolbox --- src/qt/bitcoingui.cpp | 4 +-- src/qt/forms/lookupaddressdialog.ui | 17 +++++++++++ src/qt/lookupaddressdialog.cpp | 46 ++++++++++++++++++++++++++--- src/qt/walletview.cpp | 19 ++++++------ 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 99212790a7889..49ee3f63d7ba7 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -259,7 +259,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) smartPropertyAction->setToolTip(smartPropertyAction->statusTip()); smartPropertyAction->setCheckable(true); smartPropertyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); - tabGroup->addAction(smartPropertyAction); +// tabGroup->addAction(smartPropertyAction); historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); @@ -423,7 +423,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); toolbar->addAction(exchangeAction); - toolbar->addAction(smartPropertyAction); +// toolbar->addAction(smartPropertyAction); toolbar->addAction(historyAction); toolbar->addAction(toolboxAction); overviewAction->setChecked(true); diff --git a/src/qt/forms/lookupaddressdialog.ui b/src/qt/forms/lookupaddressdialog.ui index ffbf8fc37b72a..86a643ab7334e 100644 --- a/src/qt/forms/lookupaddressdialog.ui +++ b/src/qt/forms/lookupaddressdialog.ui @@ -188,6 +188,23 @@ + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Key In Wallet: + + + diff --git a/src/qt/lookupaddressdialog.cpp b/src/qt/lookupaddressdialog.cpp index f728ca67dbf5f..fd126c47bd64b 100644 --- a/src/qt/lookupaddressdialog.cpp +++ b/src/qt/lookupaddressdialog.cpp @@ -72,6 +72,17 @@ LookupAddressDialog::LookupAddressDialog(QWidget *parent) : // connect actions connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); + + // hide balance labels + QLabel* balances[] = { ui->propertyLabel1, ui->propertyLabel2, ui->propertyLabel3, ui->propertyLabel4, ui->propertyLabel5, ui->propertyLabel6, ui->propertyLabel7, ui->propertyLabel8, ui->propertyLabel9, ui->propertyLabel10 }; + QLabel* labels[] = { ui->property1, ui->property2, ui->property3, ui->property4, ui->property5, ui->property6, ui->property7, ui->property8, ui->property9, ui->property10 }; + int pItem = 0; + for (pItem = 1; pItem < 11; pItem++) + { + labels[pItem-1]->setVisible(false); + balances[pItem-1]->setVisible(false); + } + ui->onlyLabel->setVisible(false); } void LookupAddressDialog::searchAddress() @@ -91,6 +102,7 @@ void LookupAddressDialog::searchAddress() ui->addressLabel->setText(QString::fromStdString(searchText)); if ((searchText.substr(0,1) == "1") || (searchText.substr(0,1) == "m") || (searchText.substr(0,1) == "n")) ui->addressTypeLabel->setText("Public Key Hash"); if ((searchText.substr(0,1) == "2") || (searchText.substr(0,1) == "3")) ui->addressTypeLabel->setText("Pay to Script Hash"); + if (IsMyAddress(searchText)) { ui->isMineLabel->setText("True"); } else { ui->isMineLabel->setText("False"); } //scrappy way to do this, find a more efficient way of interacting with labels //show first 10 SPs with balances - needs to be converted to listwidget or something @@ -106,7 +118,7 @@ void LookupAddressDialog::searchAddress() for (pItem = 1; pItem < 12; pItem++) { pFound[pItem] = false; - for (propertyId = lastFoundPropertyIdMainEco+1; propertyId<100000; propertyId++) + for (propertyId = lastFoundPropertyIdMainEco+1; propertyId<10000; propertyId++) { foundProperty=false; if (getUserAvailableMPbalance(searchText, propertyId) > 0) @@ -114,7 +126,7 @@ void LookupAddressDialog::searchAddress() lastFoundPropertyIdMainEco = propertyId; foundProperty=true; pName[pItem] = getPropertyName(propertyId).c_str(); - if(pName[pItem].size()>22) pName[pItem]=pName[pItem].substr(0,22)+"..."; + if(pName[pItem].size()>32) pName[pItem]=pName[pItem].substr(0,32)+"..."; pName[pItem] += " (#" + static_cast( &(ostringstream() << propertyId) )->str() + ")"; pBal[pItem] = getUserAvailableMPbalance(searchText, propertyId); pDivisible[pItem] = isPropertyDivisible(propertyId); @@ -126,14 +138,14 @@ void LookupAddressDialog::searchAddress() // have we found a property in main eco? If not let's try test eco if (!foundProperty) { - for (propertyId = lastFoundPropertyIdTestEco+1; propertyId<100000; propertyId++) + for (propertyId = lastFoundPropertyIdTestEco+1; propertyId<10000; propertyId++) { if (getUserAvailableMPbalance(searchText, propertyId+2147483647) > 0) { lastFoundPropertyIdTestEco = propertyId; foundProperty=true; pName[pItem] = getPropertyName(propertyId+2147483647).c_str(); - if(pName[pItem].size()>22) pName[pItem]=pName[pItem].substr(0,22)+"..."; + if(pName[pItem].size()>32) pName[pItem]=pName[pItem].substr(0,32)+"..."; pName[pItem] += " (#" + static_cast( &(ostringstream() << propertyId+2147483647) )->str() + ")"; pBal[pItem] = getUserAvailableMPbalance(searchText, propertyId+2147483647); pDivisible[pItem] = isPropertyDivisible(propertyId+2147483647); @@ -174,6 +186,32 @@ void LookupAddressDialog::searchAddress() balances[pItem-1]->setVisible(false); } } + if (pFound[11]) { ui->onlyLabel->setVisible(true); } else { ui->onlyLabel->setVisible(false); } + } + else + { + // hide balance labels + QLabel* balances[] = { ui->propertyLabel1, ui->propertyLabel2, ui->propertyLabel3, ui->propertyLabel4, ui->propertyLabel5, ui->propertyLabel6, ui->propertyLabel7, ui->propertyLabel8, ui->propertyLabel9, ui->propertyLabel10 }; + QLabel* labels[] = { ui->property1, ui->property2, ui->property3, ui->property4, ui->property5, ui->property6, ui->property7, ui->property8, ui->property9, ui->property10 }; + int pItem = 0; + for (pItem = 1; pItem < 11; pItem++) + { + labels[pItem-1]->setVisible(false); + balances[pItem-1]->setVisible(false); + } + ui->addressLabel->setText("N/A"); + ui->addressTypeLabel->setText("N/A"); + ui->isMineLabel->setText("N/A"); + // show error message + string strText = "The address entered was not valid."; + QString strQText = QString::fromStdString(strText); + QMessageBox errorDialog; + errorDialog.setIcon(QMessageBox::Critical); + errorDialog.setWindowTitle("Address error"); + errorDialog.setText(strQText); + errorDialog.setStandardButtons(QMessageBox::Ok); + errorDialog.setDefaultButton(QMessageBox::Ok); + if(errorDialog.exec() == QMessageBox::Ok) { } // no other button to choose, acknowledged } } diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index c96c0e82fc3e4..6386abbe5dde2 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -119,26 +119,27 @@ WalletView::WalletView(QWidget *parent): exchangePage->setLayout(exvbox); // smart property page - smartPropertyPage = new QWidget(this); + /*smartPropertyPage = new QWidget(this); QVBoxLayout *spvbox = new QVBoxLayout(); - spLookupTab = new LookupSPDialog(); QTabWidget *spTabHolder = new QTabWidget(); - spTabHolder->addTab(spLookupTab,tr("Lookup Property")); spTabHolder->addTab(new QWidget(),tr("Crowdsale Participation")); -// spTabHolder->addTab(new QWidget(),tr("Property Issuance")); -// spTabHolder->addTab(new QWidget(),tr("Revoke or Grant Tokens")); + spTabHolder->addTab(new QWidget(),tr("Property Issuance")); + spTabHolder->addTab(new QWidget(),tr("Revoke or Grant Tokens")); spvbox->addWidget(spTabHolder); smartPropertyPage->setLayout(spvbox); + */ // toolbox page toolboxPage = new QWidget(this); QVBoxLayout *tvbox = new QVBoxLayout(); addressLookupTab = new LookupAddressDialog(); + spLookupTab = new LookupSPDialog(); // txLookupTab = new LookupTXDialog(); QTabWidget *tTabHolder = new QTabWidget(); - tTabHolder->addTab(addressLookupTab,tr("Search Address")); -// tTabHolder->addTab(txLookupTab,tr("Search Transaction"); - tTabHolder->addTab(new QWidget(),tr("Search Transaction")); + tTabHolder->addTab(addressLookupTab,tr("Lookup Address")); + tTabHolder->addTab(spLookupTab,tr("Lookup Property")); +// tTabHolder->addTab(txLookupTab,tr("Lookup Transaction"); + tTabHolder->addTab(new QWidget(),tr("Lookup Transaction")); tvbox->addWidget(tTabHolder); toolboxPage->setLayout(tvbox); @@ -150,7 +151,7 @@ WalletView::WalletView(QWidget *parent): addWidget(receiveCoinsPage); addWidget(sendCoinsPage); addWidget(exchangePage); - addWidget(smartPropertyPage); + //addWidget(smartPropertyPage); addWidget(toolboxPage); // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page From 9b6e3df656c84f96a39c3b49ef618f976b07c451 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 13:10:58 -0800 Subject: [PATCH 048/141] Add free text search to property lookup --- src/qt/forms/lookupspdialog.ui | 1531 ++++++++++++++++---------------- src/qt/lookupspdialog.cpp | 42 +- 2 files changed, 787 insertions(+), 786 deletions(-) diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui index a7019ed9cf36d..5409421090889 100644 --- a/src/qt/forms/lookupspdialog.ui +++ b/src/qt/forms/lookupspdialog.ui @@ -1,782 +1,749 @@ - - - LookupSPDialog - - - - 0 - 0 - 664 - 474 - - - - Form - - - - - - false - - - background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; - - - true - - - 3 - - - - - - - 0 - - - - - true - - - - 130 - 0 - - - - Search Smart Property: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 8 - - - - - - - - - - Search - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 20 - - - - - - - - - - 0 - - - - - - 130 - 0 - - - - Matching Results: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 8 - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 20 - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - 75 - true - - - - Smart Property Information - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - - - - - 0 - - - - - Property ID: - - - - - - - - 75 - true - - - - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Issuer: - - - - - - - - 0 - 0 - - - - - 75 - true - - - - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 - - - -1 - - - - - - - - - Name: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Category: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Subcategory: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - URL: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Data: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 20 - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - <b>Token Information</b> - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - - - - 75 - true - - - - Fixed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Test - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Qt::LeftToRight - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - No - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Divisible: - - - - - - - Issuance Type: - - - - - - - Ecosystem: - - - - - - - Total Tokens: - - - - - - - Wallet Balance: - - - - - - - - 75 - true - - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - 12 - - - - - - 75 - true - - - - Crowdsale Information - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - 0 - - - - - Desired Property: - - - - - - - - 75 - true - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Tokens Per Unit: - - - - - - - - 75 - true - - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Deadline: - - - - - - - - 75 - true - - - - N/A - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Estimated Bonus: - - - - - - - - 75 - true - - - - 0% - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Issuer Percentage: - - - - - - - - 75 - true - - - - 0% - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Purchase - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - + + + LookupSPDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + true + + + + 130 + 0 + + + + Search Smart Property: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + + + Search + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + 0 + + + + + + 130 + 0 + + + + Matching Results: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + 75 + true + + + + Smart Property Information + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + + + 0 + + + + + Property ID: + + + + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + -1 + + + + + + + + + Name: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Category: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Subcategory: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + URL: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + Data: + + + + + + + + 75 + true + + + + padding-left:8px;padding-bottom:10px; + + + N/A + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + <b>Token Information</b> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + + + + 75 + true + + + + Fixed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Test + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + Qt::LeftToRight + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + + + + No + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Divisible: + + + + + + + Issuance Type: + + + + + + + Ecosystem: + + + + + + + Total Tokens: + + + + + + + Wallet Balance: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 12 + + + + + + 75 + true + + + + Crowdsale Information + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 0 + + + + + Desired Property: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Tokens Per Unit: + + + + + + + + 75 + true + + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Deadline: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Estimated Bonus: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer Percentage: + + + + + + + + 75 + true + + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp index 9ac619dfd4993..dfc87703cf151 100644 --- a/src/qt/lookupspdialog.cpp +++ b/src/qt/lookupspdialog.cpp @@ -79,7 +79,6 @@ void LookupSPDialog::searchSP() { // search function to lookup properties, we want this search function to be as capable as possible to // help users find the property they're looking for via search terms they may want to use -printf("search\n"); int searchParamType = 0; string searchText = ui->searchLineEdit->text().toStdString(); unsigned int searchPropertyId = 0; @@ -96,7 +95,7 @@ printf("search\n"); catch(const boost::bad_lexical_cast &e) { } if (searchParamType == 1 && 0 >= searchPropertyId) searchParamType = 0; // we got a number but it's <=0 - // next if not positive numerical, lets see if the string is a valid bitcoin address + // next if not positive numerical, lets see if the string is a valid bitcoin address for issuer search if (searchParamType == 0) { CBitcoinAddress address; @@ -106,7 +105,6 @@ printf("search\n"); // if we still don't have a param we'll search against free text in the name if (searchParamType == 0) searchParamType = 3; // search by free text -printf("selected search type is %d\n", searchParamType); // clear matching results combo ui->matchingComboBox->clear(); @@ -127,7 +125,7 @@ printf("selected search type is %d\n", searchParamType); if (spExists) { addSPToMatchingResults(propertyId); - updateDisplayedProperty(); + updateDisplayedProperty(); //show straight away, only one to select } else { @@ -164,6 +162,42 @@ printf("selected search type is %d\n", searchParamType); break; case 3: //search by freetext // iterate through my_sps and see if property name contains the search text + nextSPID = _my_sps->peekNextSPID(1); + nextTestSPID = _my_sps->peekNextSPID(2); + for (tmpPropertyId = 1; tmpPropertyIdgetSP(tmpPropertyId, sp)) + { + // make the search case insensitive + string lowerName = sp.name; + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); + string lowerSearch = searchText; + std::transform(lowerSearch.begin(), lowerSearch.end(), lowerSearch.begin(), ::tolower); + size_t loc = lowerName.find(lowerSearch); + if (loc!=std::string::npos) + { + addSPToMatchingResults(tmpPropertyId); + } + } + } + for (tmpPropertyId = TEST_ECO_PROPERTY_1; tmpPropertyIdgetSP(tmpPropertyId, sp)) + { + // make the search case insensitive + string lowerName = sp.name; + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); + string lowerSearch = searchText; + std::transform(lowerSearch.begin(), lowerSearch.end(), lowerSearch.begin(), ::tolower); + size_t loc = lowerName.find(lowerSearch); + if (loc!=std::string::npos) + { + addSPToMatchingResults(tmpPropertyId); + } + } + } break; } From 4bbc1b90c805d6c7844ebd8a1c3114416c847205 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 14:57:36 -0800 Subject: [PATCH 049/141] fix up property lookup --- src/qt/forms/lookupspdialog.ui | 772 +++++++++++++++++---------------- src/qt/lookupspdialog.cpp | 85 +++- 2 files changed, 472 insertions(+), 385 deletions(-) diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui index 5409421090889..34b1000c5e9fb 100644 --- a/src/qt/forms/lookupspdialog.ui +++ b/src/qt/forms/lookupspdialog.ui @@ -42,23 +42,36 @@ - 130 + 0 0 - Search Smart Property: + Search: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - 8 + 0 - + + + + 0 + 0 + + + + + 150 + 0 + + + @@ -67,45 +80,25 @@ - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 6 - 20 - - - - - - - - - - 0 - - 130 + 0 0 + + padding-left:15px; + - Matching Results: + Results: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - 8 + 0 @@ -119,21 +112,239 @@ + + + + + + 0 + - - - Qt::Horizontal + + + QFrame::StyledPanel - - QSizePolicy::Fixed + + QFrame::Raised - - - 6 - 20 - - - + + + + + + + + + + 75 + true + + + + Smart Property Information + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 0 + + + + + Property ID: + + + + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Name: + + + + + + + + 75 + true + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Issuer: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + color:rgb(148, 148, 148) + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + -1 + + + + + + + Category: + + + + + + + + 50 + false + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + URL: + + + + + + + + 50 + false + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Data: + + + + + + + + 50 + false + + + + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + name + + + @@ -151,11 +362,44 @@ - + + + 0 + - + - + + + <b>Token Information</b> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 75 @@ -163,218 +407,117 @@ - Smart Property Information + Fixed + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - - - - - 0 - - - + + + + + 75 + true + + - Property ID: + Test + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + 75 true - - + + Qt::LeftToRight + + + 0 SPT + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 75 + true + - N/A + No Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Divisible: + + + - + - Issuer: + Issuance Type: - - - - - 0 - 0 - + + + + Ecosystem: + + + + + + + Total Tokens: + + + + + + + Wallet Balance: + + + + 75 true - - - - N/A + 0 SPT Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 0 - - - -1 - - - - - Name: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Category: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Subcategory: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - URL: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - - - - - Data: - - - - - - - - 75 - true - - - - padding-left:8px;padding-bottom:10px; - - - N/A - - - @@ -409,162 +552,10 @@ QFrame::Raised - - - - - - <b>Token Information</b> - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - - - - 75 - true - - - - Fixed - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Test - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - Qt::LeftToRight - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 75 - true - - - - No - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Divisible: - - - - - - - Issuance Type: - - - - - - - Ecosystem: - - - - - - - Total Tokens: - - - - - - - Wallet Balance: - - - - - - - - 75 - true - - - - 0 SPT - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 12 + 0 @@ -605,14 +596,14 @@ 0 - + Desired Property: - + @@ -628,14 +619,14 @@ - + Tokens Per Unit: - + @@ -651,14 +642,14 @@ - + Deadline: - + @@ -674,14 +665,14 @@ - + - Estimated Bonus: + Weekly Bonus: - + @@ -697,14 +688,14 @@ - + Issuer Percentage: - + @@ -720,6 +711,29 @@ + + + + Active: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp index dfc87703cf151..7cf35e5440e26 100644 --- a/src/qt/lookupspdialog.cpp +++ b/src/qt/lookupspdialog.cpp @@ -58,6 +58,7 @@ using namespace leveldb; #include #include #include +#include LookupSPDialog::LookupSPDialog(QWidget *parent) : QDialog(parent), @@ -68,11 +69,25 @@ LookupSPDialog::LookupSPDialog(QWidget *parent) : this->model = model; // populate placeholder text - ui->searchLineEdit->setPlaceholderText("Search property ID, issuer or property name"); + ui->searchLineEdit->setPlaceholderText("ID, name or issuer"); // connect actions connect(ui->matchingComboBox, SIGNAL(activated(int)), this, SLOT(matchingComboBoxChanged(int))); connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); + + // hide crowd info + ui->desired->setVisible(false); + ui->tokensperunit->setVisible(false); + ui->deadline->setVisible(false); + ui->bonus->setVisible(false); + ui->issuerperc->setVisible(false); + ui->desiredLabel->setVisible(false); + ui->tokensPerUnitLabel->setVisible(false); + ui->deadlineLabel->setVisible(false); + ui->bonusLabel->setVisible(false); + ui->issuerPercLabel->setVisible(false); + ui->activeLabel->setVisible(false); + ui->active->setText("Not applicable."); } void LookupSPDialog::searchSP() @@ -211,7 +226,7 @@ void LookupSPDialog::addSPToMatchingResults(unsigned int propertyId) { string spName; spName = getPropertyName(propertyId).c_str(); - if(spName.size()>30) spName=spName.substr(0,30)+"..."; + if(spName.size()>50) spName=spName.substr(0,50)+"..."; string spId = static_cast( &(ostringstream() << propertyId) )->str(); spName += " (#" + spId + ")"; ui->matchingComboBox->addItem(spName.c_str(),spId.c_str()); @@ -239,8 +254,7 @@ void LookupSPDialog::updateDisplayedProperty() if (propertyId>2147483647) { ui->ecosystemLabel->setText("Test"); } else { ui->ecosystemLabel->setText("Production"); } ui->propertyIDLabel->setText(QString::fromStdString(FormatIndivisibleMP(propertyId))); ui->nameLabel->setText(QString::fromStdString(sp.name)); - ui->categoryLabel->setText(QString::fromStdString(sp.category)); - ui->subcategoryLabel->setText(QString::fromStdString(sp.subcategory)); + ui->categoryLabel->setText(QString::fromStdString(sp.category + " > " + sp.subcategory)); ui->dataLabel->setText(QString::fromStdString(sp.data)); ui->urlLabel->setText(QString::fromStdString(sp.url)); string strTotalTokens; @@ -265,8 +279,67 @@ void LookupSPDialog::updateDisplayedProperty() ui->totalTokensLabel->setText(QString::fromStdString(strTotalTokens + tokenLabel)); ui->walletBalanceLabel->setText(QString::fromStdString(strWalletTokens + tokenLabel)); ui->issuerLabel->setText(QString::fromStdString(sp.issuer)); - // issuances are no longer just fixed or variable, this needs further code changes to sp.fixed - //bool fixedIssuance = sp.fixed; + bool fixedIssuance = sp.fixed; + bool manualIssuance = sp.manual; + if ((!fixedIssuance) && (!manualIssuance) && (propertyId > 2)) + { + ui->issuanceTypeLabel->setText("Crowdsale"); + // obtain crowdinfo + bool active = isCrowdsaleActive(propertyId); + int64_t deadline = sp.deadline; + uint8_t earlyBonus = sp.early_bird; + uint8_t percentToIssuer = sp.percentage; + int64_t tokensPerUnit = sp.num_tokens; + int64_t propertyIdDesired = sp.property_desired; + QDateTime qDeadline; + qDeadline.setTime_t(deadline); + string desiredText = getPropertyName(propertyIdDesired).c_str(); + if(desiredText.size()>22) desiredText=desiredText.substr(0,22)+"..."; + string spId = static_cast( &(ostringstream() << propertyIdDesired) )->str(); + desiredText += " (#" + spId + ")"; + string tokensPerUnitText; + if (divisible) { tokensPerUnitText = FormatDivisibleMP(tokensPerUnit); } else { tokensPerUnitText = FormatIndivisibleMP(tokensPerUnit); } + if (active) { ui->activeLabel->setText("Yes"); } else { ui->activeLabel->setText("No"); } + // populate crowdinfo + ui->desiredLabel->setText(QString::fromStdString(desiredText)); + ui->tokensPerUnitLabel->setText(QString::fromStdString(tokensPerUnitText)); + ui->deadlineLabel->setText(qDeadline.toString(Qt::SystemLocaleShortDate)); + ui->bonusLabel->setText(QString::fromStdString(FormatIndivisibleMP((int64_t)earlyBonus) + "%")); + ui->issuerPercLabel->setText(QString::fromStdString(FormatIndivisibleMP((int64_t)percentToIssuer) + "%")); + // show crowdinfo + ui->desired->setVisible(true); + ui->tokensperunit->setVisible(true); + ui->deadline->setVisible(true); + ui->bonus->setVisible(true); + ui->issuerperc->setVisible(true); + ui->desiredLabel->setVisible(true); + ui->tokensPerUnitLabel->setVisible(true); + ui->deadlineLabel->setVisible(true); + ui->bonusLabel->setVisible(true); + ui->issuerPercLabel->setVisible(true); + ui->activeLabel->setVisible(true); + ui->active->setText("Active:"); + } + else + { + ui->issuanceTypeLabel->setText("Exodus"); + if (fixedIssuance) ui->issuanceTypeLabel->setText("Fixed"); + if (manualIssuance) ui->issuanceTypeLabel->setText("Manual"); + // hide crowdinfo + ui->desired->setVisible(false); + ui->tokensperunit->setVisible(false); + ui->deadline->setVisible(false); + ui->bonus->setVisible(false); + ui->issuerperc->setVisible(false); + ui->desiredLabel->setVisible(false); + ui->tokensPerUnitLabel->setVisible(false); + ui->deadlineLabel->setVisible(false); + ui->bonusLabel->setVisible(false); + ui->issuerPercLabel->setVisible(false); + ui->activeLabel->setVisible(false); + ui->active->setText("Not applicable."); + } + } void LookupSPDialog::searchButtonClicked() From 54380448b91ff11c3fffd7865659795207d98450 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 15:13:48 -0800 Subject: [PATCH 050/141] Add UI elements for tx history --- src/qt/Makefile.am | 7 + src/qt/forms/txhistorydialog.ui | 31 ++++ src/qt/txhistorydialog.cpp | 283 ++++++++++++++++++++++++++++++++ src/qt/txhistorydialog.h | 53 ++++++ src/qt/txlistdelegate.cpp | 106 ++++++++++++ src/qt/txlistdelegate.h | 14 ++ 6 files changed, 494 insertions(+) create mode 100644 src/qt/forms/txhistorydialog.ui create mode 100644 src/qt/txhistorydialog.cpp create mode 100644 src/qt/txhistorydialog.h create mode 100644 src/qt/txlistdelegate.cpp create mode 100644 src/qt/txlistdelegate.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index fc734ceb468dc..7ccc07ececf72 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -102,6 +102,7 @@ QT_FORMS_UI = \ forms/sendcoinsentry.ui \ forms/sendmpdialog.ui \ forms/orderhistorydialog.ui \ + forms/txhistorydialog.ui \ forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/lookupaddressdialog.ui \ @@ -143,6 +144,8 @@ QT_MOC_CPP = \ moc_sendmpdialog.cpp \ moc_metadexdialog.cpp \ moc_orderhistorydialog.cpp \ + moc_txhistorydialog.cpp \ + moc_txlistdelegate.cpp \ moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ moc_lookupaddressdialog.cpp \ @@ -214,9 +217,11 @@ BITCOIN_QT_H = \ sendmpdialog.h \ metadexdialog.h \ orderhistorydialog.h \ + txhistorydialog.h \ lookupspdialog.h \ lookupaddressdialog.h \ orderlistdelegate.h \ + txlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ trafficgraphwidget.h \ @@ -335,7 +340,9 @@ BITCOIN_QT_CPP += \ sendmpdialog.cpp \ metadexdialog.cpp \ orderhistorydialog.cpp \ + txhistorydialog.cpp \ orderlistdelegate.cpp \ + txlistdelegate.cpp \ lookupspdialog.cpp \ lookupaddressdialog.cpp \ signverifymessagedialog.cpp \ diff --git a/src/qt/forms/txhistorydialog.ui b/src/qt/forms/txhistorydialog.ui new file mode 100644 index 0000000000000..d8e48cce8bfb3 --- /dev/null +++ b/src/qt/forms/txhistorydialog.ui @@ -0,0 +1,31 @@ + + + txHistoryDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + 0 + + + + + + + + + + + diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp new file mode 100644 index 0000000000000..5f184d91a5e36 --- /dev/null +++ b/src/qt/txhistorydialog.cpp @@ -0,0 +1,283 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "txhistorydialog.h" +#include "ui_txhistorydialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +using namespace json_spirit; +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" +#include "mastercore_parse_string.h" + +#include +#include +#include +#include + +#include "txlistdelegate.h" + +TXHistoryDialog::TXHistoryDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::txHistoryDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; + ui->txHistoryLW->setItemDelegate(new ListDelegate(ui->txHistoryLW)); + + CWallet *wallet = pwalletMain; + string sAddress = ""; + string addressParam = ""; + bool addressFilter; + + addressFilter = false; + int64_t nCount = 10; + int64_t nFrom = 0; + int64_t nStartBlock = 0; + int64_t nEndBlock = 999999; + + Array response; //prep an array to hold our output + + // rewrite to use original listtransactions methodology from core + LOCK(wallet->cs_wallet); + std::list acentries; + CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); + + // iterate backwards + for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + if (pwtx != 0) + { + uint256 hash = pwtx->GetHash(); + CTransaction wtx; + uint256 blockHash = 0; + if (!GetTransaction(hash, wtx, blockHash, true)) continue; + // get the time of the tx + int64_t nTime = pwtx->GetTxTime(); + // get the height of the transaction and check it's within the chosen parameters + blockHash = pwtx->hashBlock; + if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue; + CBlockIndex* pBlockIndex = mapBlockIndex[blockHash]; + if (NULL == pBlockIndex) continue; + int blockHeight = pBlockIndex->nHeight; + if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range + // check if the transaction exists in txlist, and if so is it correct type (21) + if (p_txlistdb->exists(hash)) + { + // get type from levelDB + string strValue; + if (!p_txlistdb->getTX(hash, strValue)) continue; + std::vector vstr; + boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); + if (4 <= vstr.size()) + { + // if tx21, get the details for the list + if(21 == atoi(vstr[2])) + { + string statusText; + unsigned int propertyIdForSale = 0; + unsigned int propertyIdDesired = 0; + uint64_t amountForSale = 0; + uint64_t amountDesired = 0; + string address; + bool divisibleForSale; + bool divisibleDesired; + bool valid; + Array tradeArray; + uint64_t totalBought = 0; + uint64_t totalSold = 0; + bool orderOpen = false; + + CMPMetaDEx temp_metadexoffer; + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity + { + if (0<=mp_obj.step1()) + { + //MPTxType = mp_obj.getTypeString(); + //MPTxTypeInt = mp_obj.getType(); + address = mp_obj.getSender(); + //if (!filterAddress.empty()) if ((senderAddress != filterAddress) && (refAddress != filterAddress)) return -1; // return negative rc if filtering & no match + + int tmpblock=0; + uint32_t tmptype=0; + uint64_t amountNew=0; + valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew); + + if (0 == mp_obj.step2_Value()) + { + propertyIdForSale = mp_obj.getProperty(); + amountForSale = mp_obj.getAmount(); + divisibleForSale = isPropertyDivisible(propertyIdForSale); + if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) + { + propertyIdDesired = temp_metadexoffer.getDesProperty(); + divisibleDesired = isPropertyDivisible(propertyIdDesired); + amountDesired = temp_metadexoffer.getAmountDesired(); + //mdex_action = temp_metadexoffer.getAction(); + t_tradelistdb->getMatchingTrades(hash, propertyIdForSale, &tradeArray, &totalSold, &totalBought); + + // status - is order cancelled/closed-filled/open/open-partialfilled? + // is the sell offer still open - need more efficient way to do this + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + if (my_it->first == propertyIdForSale) //at minimum only go deeper if it's the right property id + { + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + md_Set & indexes = (it->second); + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if( obj.getHash().GetHex() == hash.GetHex() ) orderOpen = true; + } + } + } + } + } + } + } + } + + // work out status + bool partialFilled = false; + bool filled = false; + if(totalSold>0) partialFilled = true; + if(totalSold>=amountForSale) filled = true; + statusText = "UNKNOWN"; + if((!orderOpen) && (!partialFilled)) statusText = "CANCELLED"; + if((!orderOpen) && (partialFilled)) statusText = "PART CANCEL"; + if((!orderOpen) && (filled)) statusText = "FILLED"; + if((orderOpen) && (!partialFilled)) statusText = "OPEN"; + if((orderOpen) && (partialFilled)) statusText = "PART FILLED"; + + // add to list + QListWidgetItem *qItem = new QListWidgetItem(); + qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); + string displayText = "Sell "; + string displayIn = "+"; + string displayOut = "-"; + string displayInToken; + string displayOutToken; + + if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } + if(propertyIdForSale < 3) + { + if(propertyIdForSale == 1) { displayText += " MSC for "; displayOutToken = " MSC"; } + if(propertyIdForSale == 2) { displayText += " TMSC for "; displayOutToken = " TMSC"; } + } + else + { + string s = to_string(propertyIdForSale); + displayText += " SPT#" + s + " for "; + displayOutToken = " SPT#" + s; + } + if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } + if(propertyIdDesired < 3) + { + if(propertyIdDesired == 1) { displayText += " MSC"; displayInToken = " MSC"; } + if(propertyIdDesired == 2) { displayText += " TMSC"; displayInToken = " TMSC"; } + } + else + { + string s = to_string(propertyIdDesired); + displayText += " SPT#" + s; + displayInToken = " SPT#" + s; + } + if(divisibleDesired) { displayIn += FormatDivisibleMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } + if(divisibleForSale) { displayOut += FormatDivisibleMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } + if(totalBought == 0) displayIn = "0"; + if(totalSold == 0) displayOut = "0"; + displayIn += displayInToken; + displayOut += displayOutToken; + QDateTime txTime; + txTime.setTime_t(nTime); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); + qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); + qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); + qItem->setData(Qt::UserRole + 4, QString::fromStdString(statusText)); + qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); + qItem->setData(Qt::UserRole + 6, txTimeStr); + ui->txHistoryLW->addItem(qItem); + } + } + } + // don't burn time doing more work than we need to +// if ((int)response.size() >= (nCount+nFrom)) break; + } + } + // sort array here and cut on nFrom and nCount +// if (nFrom > (int)response.size()) +// nFrom = response.size(); +// if ((nFrom + nCount) > (int)response.size()) +// nCount = response.size() - nFrom; +// Array::iterator first = response.begin(); +// std::advance(first, nFrom); +// Array::iterator last = response.begin(); +// std::advance(last, nFrom+nCount); + +// if (last != response.end()) response.erase(last, response.end()); +// if (first != response.begin()) response.erase(response.begin(), first); + +// std::reverse(response.begin(), response.end()); // return oldest to newest? + // return response; // return response array for JSON serialization + +} + +void TXHistoryDialog::setModel(WalletModel *model) +{ + this->model = model; + //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); +} + diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h new file mode 100644 index 0000000000000..ae438648a1e82 --- /dev/null +++ b/src/qt/txhistorydialog.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef TXHISTORYDIALOG_H +#define TXHISTORYDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class txHistoryDialog; +} + +/** Dialog for looking up Master Protocol tokens */ +class TXHistoryDialog : public QDialog +{ + Q_OBJECT + +public: + //void FullRefresh(); + explicit TXHistoryDialog(QWidget *parent = 0); + void setModel(WalletModel *model); + + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + +public slots: + //void switchButtonClicked(); + +private: + Ui::txHistoryDialog *ui; + WalletModel *model; + +private slots: + //void buyRecalc(); + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // ORDERHISTORYDIALOG_H diff --git a/src/qt/txlistdelegate.cpp b/src/qt/txlistdelegate.cpp new file mode 100644 index 0000000000000..c39e8c6f34b08 --- /dev/null +++ b/src/qt/txlistdelegate.cpp @@ -0,0 +1,106 @@ +#include "txlistdelegate.h" + +ListDelegate::ListDelegate(QObject *parent) +{ + +} + +void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + QRect r = option.rect; + QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); + QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); + painter->setPen(linePen); + + // alt the colors + painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); + painter->drawRect(r); + // draw border + painter->setPen(linePen); + painter->drawLine(r.topLeft(),r.topRight()); + painter->drawLine(r.topRight(),r.bottomRight()); + painter->drawLine(r.bottomLeft(),r.bottomRight()); + painter->drawLine(r.topLeft(),r.bottomLeft()); + painter->setPen(fontPen); + + // prepare the data for the entry +// QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); +// string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); + QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; + txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; +// txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); + QString displayText = index.data(Qt::UserRole + 1).toString(); + QString amountBought = index.data(Qt::UserRole + 2).toString(); + QString amountSold = index.data(Qt::UserRole + 3).toString(); + QString status = index.data(Qt::UserRole + 4).toString(); + QString senderText = index.data(Qt::UserRole + 5).toString(); + QString txTimeText = index.data(Qt::UserRole + 6).toString(); + + // add the appropriate status icon + int imageSpace = 10; + QIcon ic = QIcon(":/icons/meta_cancelled"); + if(status == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); + if(status == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); + if(status == "FILLED") ic = QIcon(":/icons/meta_filled"); + if(status == "OPEN") ic = QIcon(":/icons/meta_open"); + if(status == "PART FILLED") ic = QIcon(":/icons/meta_partial"); + if (!ic.isNull()) + { + r = option.rect.adjusted(5, 10, -10, -10); + ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); + imageSpace = 60; + } + + // setup pens + QPen penBlack(QColor("#000000")); + QPen penRed(QColor("#CC0000")); + QPen penGreen(QColor("#00AA00")); + QPen penGrey(QColor("#606060")); + + QFont font = painter->font(); + painter->setPen(penBlack); + // add the status + font.setItalic(false); + painter->setFont(font); + r = option.rect.adjusted(imageSpace-19, 0, -10, -25); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); + // add the datetime + painter->setPen(penGrey); + font.setItalic(true); + painter->setFont(font); + r = option.rect.adjusted(imageSpace-19, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txTimeText, &r); + // add the displaytext + painter->setPen(penBlack); + r = option.rect.adjusted(imageSpace+115, 0, -10, -25); + font.setBold(true); + font.setItalic(false); + painter->setFont(font); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); + // add the txid/sender + painter->setPen(penGrey); + font.setBold(false); + painter->setFont(font); + r = option.rect.adjusted(imageSpace+115, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidsender, &r); + font.setBold(true); + painter->setFont(font); + if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); + r = option.rect.adjusted(imageSpace+115, 0, -10, -25); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); + if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); + r = option.rect.adjusted(imageSpace+115, 25, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); + font.setBold(false); + painter->setFont(font); + +} + +QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + return QSize(200, 50); // very dumb value? +} + +ListDelegate::~ListDelegate() +{ +} diff --git a/src/qt/txlistdelegate.h b/src/qt/txlistdelegate.h new file mode 100644 index 0000000000000..c1912d979825f --- /dev/null +++ b/src/qt/txlistdelegate.h @@ -0,0 +1,14 @@ +#include +#include + +class ListDelegate : public QAbstractItemDelegate +{ + public: + ListDelegate(QObject *parent = 0); + + void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; + + virtual ~ListDelegate(); + +}; From 0c342e05ff51af1492a5d475915a2a88b0fbdbac Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 15:27:52 -0800 Subject: [PATCH 051/141] enable the tx history tab --- src/qt/metadexdialog.cpp | 1 - src/qt/walletview.cpp | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 2f800f0f47976..7fea6d8c2068b 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -66,7 +66,6 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui(new Ui::MetaDExDialog), model(0) { -printf("hereme\n"); ui->setupUi(this); this->model = model; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 6386abbe5dde2..b64cde1518b37 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -23,6 +23,7 @@ #include "balancesview.h" #include "walletmodel.h" #include "orderhistorydialog.h" +#include "txhistorydialog.h" #include "ui_interface.h" #include @@ -65,9 +66,6 @@ WalletView::WalletView(QWidget *parent): // transactions page // bitcoin transactions in second tab, MP transactions in first - //masterprotocol - mpTXTab = new QWidget(); - //bitcoin bitcoinTXTab = new QWidget(this); QVBoxLayout *vbox = new QVBoxLayout(); @@ -83,7 +81,7 @@ WalletView::WalletView(QWidget *parent): hbox_buttons->addWidget(exportButton); vbox->addLayout(hbox_buttons); bitcoinTXTab->setLayout(vbox); - + mpTXTab = new TXHistoryDialog; transactionsPage = new QWidget(this); QVBoxLayout *txvbox = new QVBoxLayout(); QTabWidget *txTabHolder = new QTabWidget(); From 6c226d4bfb35b1124bfbf2ee1530e8501ce21a4c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 21:11:06 -0800 Subject: [PATCH 052/141] Updates to transaction history --- src/qt/orderlistdelegate.cpp | 2 +- src/qt/txhistorydialog.cpp | 191 ++++++++++------------------------- src/qt/txlistdelegate.cpp | 2 +- 3 files changed, 57 insertions(+), 138 deletions(-) diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp index bf74e12573a5c..459af6ed56668 100644 --- a/src/qt/orderlistdelegate.cpp +++ b/src/qt/orderlistdelegate.cpp @@ -26,7 +26,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // prepare the data for the entry // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; + QString txidsender = "ADDR: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); QString displayText = index.data(Qt::UserRole + 1).toString(); diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 5f184d91a5e36..5ff886006b9cf 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -75,9 +75,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : CWallet *wallet = pwalletMain; string sAddress = ""; string addressParam = ""; - bool addressFilter; - addressFilter = false; int64_t nCount = 10; int64_t nFrom = 0; int64_t nStartBlock = 0; @@ -112,151 +110,72 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : // check if the transaction exists in txlist, and if so is it correct type (21) if (p_txlistdb->exists(hash)) { - // get type from levelDB - string strValue; - if (!p_txlistdb->getTX(hash, strValue)) continue; - std::vector vstr; - boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); - if (4 <= vstr.size()) + string statusText; + unsigned int propertyId = 0; + uint64_t amount = 0; + string address; + bool divisible = false; + bool valid = false; + string MPTxType; + + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity { - // if tx21, get the details for the list - if(21 == atoi(vstr[2])) + if (0<=mp_obj.step1()) { - string statusText; - unsigned int propertyIdForSale = 0; - unsigned int propertyIdDesired = 0; - uint64_t amountForSale = 0; - uint64_t amountDesired = 0; - string address; - bool divisibleForSale; - bool divisibleDesired; - bool valid; - Array tradeArray; - uint64_t totalBought = 0; - uint64_t totalSold = 0; - bool orderOpen = false; + MPTxType = mp_obj.getTypeString(); + address = mp_obj.getSender(); - CMPMetaDEx temp_metadexoffer; - CMPTransaction mp_obj; - int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); - if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity - { - if (0<=mp_obj.step1()) - { - //MPTxType = mp_obj.getTypeString(); - //MPTxTypeInt = mp_obj.getType(); - address = mp_obj.getSender(); - //if (!filterAddress.empty()) if ((senderAddress != filterAddress) && (refAddress != filterAddress)) return -1; // return negative rc if filtering & no match - - int tmpblock=0; - uint32_t tmptype=0; - uint64_t amountNew=0; - valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew); - - if (0 == mp_obj.step2_Value()) - { - propertyIdForSale = mp_obj.getProperty(); - amountForSale = mp_obj.getAmount(); - divisibleForSale = isPropertyDivisible(propertyIdForSale); - if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) - { - propertyIdDesired = temp_metadexoffer.getDesProperty(); - divisibleDesired = isPropertyDivisible(propertyIdDesired); - amountDesired = temp_metadexoffer.getAmountDesired(); - //mdex_action = temp_metadexoffer.getAction(); - t_tradelistdb->getMatchingTrades(hash, propertyIdForSale, &tradeArray, &totalSold, &totalBought); - - // status - is order cancelled/closed-filled/open/open-partialfilled? - // is the sell offer still open - need more efficient way to do this - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - if (my_it->first == propertyIdForSale) //at minimum only go deeper if it's the right property id - { - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - md_Set & indexes = (it->second); - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if( obj.getHash().GetHex() == hash.GetHex() ) orderOpen = true; - } - } - } - } - } - } - } - } - - // work out status - bool partialFilled = false; - bool filled = false; - if(totalSold>0) partialFilled = true; - if(totalSold>=amountForSale) filled = true; - statusText = "UNKNOWN"; - if((!orderOpen) && (!partialFilled)) statusText = "CANCELLED"; - if((!orderOpen) && (partialFilled)) statusText = "PART CANCEL"; - if((!orderOpen) && (filled)) statusText = "FILLED"; - if((orderOpen) && (!partialFilled)) statusText = "OPEN"; - if((orderOpen) && (partialFilled)) statusText = "PART FILLED"; + int tmpblock=0; + uint32_t tmptype=0; + uint64_t amountNew=0; + valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew); - // add to list - QListWidgetItem *qItem = new QListWidgetItem(); - qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); - string displayText = "Sell "; - string displayIn = "+"; - string displayOut = "-"; - string displayInToken; - string displayOutToken; - - if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } - if(propertyIdForSale < 3) - { - if(propertyIdForSale == 1) { displayText += " MSC for "; displayOutToken = " MSC"; } - if(propertyIdForSale == 2) { displayText += " TMSC for "; displayOutToken = " TMSC"; } - } - else - { - string s = to_string(propertyIdForSale); - displayText += " SPT#" + s + " for "; - displayOutToken = " SPT#" + s; - } - if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } - if(propertyIdDesired < 3) + if (0 == mp_obj.step2_Value()) { - if(propertyIdDesired == 1) { displayText += " MSC"; displayInToken = " MSC"; } - if(propertyIdDesired == 2) { displayText += " TMSC"; displayInToken = " TMSC"; } + propertyId = mp_obj.getProperty(); + amount = mp_obj.getAmount(); + divisible = isPropertyDivisible(propertyId); } - else - { - string s = to_string(propertyIdDesired); - displayText += " SPT#" + s; - displayInToken = " SPT#" + s; - } - if(divisibleDesired) { displayIn += FormatDivisibleMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } - if(divisibleForSale) { displayOut += FormatDivisibleMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } - if(totalBought == 0) displayIn = "0"; - if(totalSold == 0) displayOut = "0"; - displayIn += displayInToken; - displayOut += displayOutToken; - QDateTime txTime; - txTime.setTime_t(nTime); - QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); - qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); - qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); - qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); - qItem->setData(Qt::UserRole + 4, QString::fromStdString(statusText)); - qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); - qItem->setData(Qt::UserRole + 6, txTimeStr); - ui->txHistoryLW->addItem(qItem); } } + QListWidgetItem *qItem = new QListWidgetItem(); + qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); + string displayType = MPTxType; + string displayAmount; + string displayToken; + string displayValid; + string displayAddress = address; + if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } + if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; } + if (propertyId < 3) + { + if(propertyId == 1) { displayToken = " MSC"; } + if(propertyId == 2) { displayToken = " TMSC"; } + } + else + { + string s = to_string(propertyId); + displayToken = " SPT#" + s; + } + string displayDirection = "out"; + QDateTime txTime; + txTime.setTime_t(nTime); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType)); + qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount)); + qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayToken)); + qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayDirection)); + qItem->setData(Qt::UserRole + 5, QString::fromStdString(displayAddress)); + qItem->setData(Qt::UserRole + 6, txTimeStr); + qItem->setData(Qt::UserRole + 7, QString::fromStdString(displayValid)); + ui->txHistoryLW->addItem(qItem); } - // don't burn time doing more work than we need to -// if ((int)response.size() >= (nCount+nFrom)) break; } } + // don't burn time doing more work than we need to +// if ((int)response.size() >= (nCount+nFrom)) break; // sort array here and cut on nFrom and nCount // if (nFrom > (int)response.size()) // nFrom = response.size(); diff --git a/src/qt/txlistdelegate.cpp b/src/qt/txlistdelegate.cpp index c39e8c6f34b08..46a606a3635a5 100644 --- a/src/qt/txlistdelegate.cpp +++ b/src/qt/txlistdelegate.cpp @@ -26,7 +26,7 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti // prepare the data for the entry // QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); // string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = "ADD: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; + QString txidsender = "ADDR: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); QString displayText = index.data(Qt::UserRole + 1).toString(); From 6f18aebab3b9ff3b00dd998ade2f89fc24b11db1 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 21:39:00 -0800 Subject: [PATCH 053/141] latest changes to txhistory --- src/qt/txhistorydialog.cpp | 13 ++++---- src/qt/txlistdelegate.cpp | 63 +++++++++++++++----------------------- src/qt/txlistdelegate.h | 6 ++-- 3 files changed, 33 insertions(+), 49 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 5ff886006b9cf..6ccc94ec9f23b 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -70,7 +70,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : { ui->setupUi(this); this->model = model; - ui->txHistoryLW->setItemDelegate(new ListDelegate(ui->txHistoryLW)); + ui->txHistoryLW->setItemDelegate(new TXListDelegate(ui->txHistoryLW)); CWallet *wallet = pwalletMain; string sAddress = ""; @@ -164,12 +164,11 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType)); - qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount)); - qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayToken)); - qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayDirection)); - qItem->setData(Qt::UserRole + 5, QString::fromStdString(displayAddress)); - qItem->setData(Qt::UserRole + 6, txTimeStr); - qItem->setData(Qt::UserRole + 7, QString::fromStdString(displayValid)); + qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + " " + displayToken)); + qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection)); + qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress)); + qItem->setData(Qt::UserRole + 5, txTimeStr); + qItem->setData(Qt::UserRole + 6, QString::fromStdString(displayValid)); ui->txHistoryLW->addItem(qItem); } } diff --git a/src/qt/txlistdelegate.cpp b/src/qt/txlistdelegate.cpp index 46a606a3635a5..b54292ddb8eb9 100644 --- a/src/qt/txlistdelegate.cpp +++ b/src/qt/txlistdelegate.cpp @@ -1,11 +1,11 @@ #include "txlistdelegate.h" -ListDelegate::ListDelegate(QObject *parent) +TXListDelegate::TXListDelegate(QObject *parent) { } -void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const +void TXListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QRect r = option.rect; QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); @@ -29,26 +29,20 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti QString txidsender = "ADDR: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; // txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); - QString displayText = index.data(Qt::UserRole + 1).toString(); - QString amountBought = index.data(Qt::UserRole + 2).toString(); - QString amountSold = index.data(Qt::UserRole + 3).toString(); - QString status = index.data(Qt::UserRole + 4).toString(); - QString senderText = index.data(Qt::UserRole + 5).toString(); - QString txTimeText = index.data(Qt::UserRole + 6).toString(); + QString displayType = index.data(Qt::UserRole + 1).toString(); + QString displayAmount = index.data(Qt::UserRole + 2).toString(); + QString displayDirection = index.data(Qt::UserRole + 3).toString(); + QString displayAddress = index.data(Qt::UserRole + 4).toString(); + QString txTimeText = index.data(Qt::UserRole + 5).toString(); // add the appropriate status icon int imageSpace = 10; QIcon ic = QIcon(":/icons/meta_cancelled"); - if(status == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); - if(status == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); - if(status == "FILLED") ic = QIcon(":/icons/meta_filled"); - if(status == "OPEN") ic = QIcon(":/icons/meta_open"); - if(status == "PART FILLED") ic = QIcon(":/icons/meta_partial"); if (!ic.isNull()) { r = option.rect.adjusted(5, 10, -10, -10); ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 60; + imageSpace = 30; } // setup pens @@ -58,49 +52,40 @@ void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & opti QPen penGrey(QColor("#606060")); QFont font = painter->font(); - painter->setPen(penBlack); - // add the status - font.setItalic(false); - painter->setFont(font); - r = option.rect.adjusted(imageSpace-19, 0, -10, -25); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); // add the datetime painter->setPen(penGrey); - font.setItalic(true); +// font.setItalic(true); painter->setFont(font); - r = option.rect.adjusted(imageSpace-19, 25, -10, 0); + r = option.rect.adjusted(imageSpace, 5, -10, 0); painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txTimeText, &r); - // add the displaytext + // add the displaytype painter->setPen(penBlack); - r = option.rect.adjusted(imageSpace+115, 0, -10, -25); - font.setBold(true); + r = option.rect.adjusted(imageSpace+125, 5, -10, 0); +// font.setBold(true); font.setItalic(false); painter->setFont(font); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); - // add the txid/sender + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayType, &r); + // add the address painter->setPen(penGrey); font.setBold(false); painter->setFont(font); - r = option.rect.adjusted(imageSpace+115, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidsender, &r); + r = option.rect.adjusted(imageSpace+250, 5, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayAddress, &r); + // add the amount font.setBold(true); painter->setFont(font); - if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); - r = option.rect.adjusted(imageSpace+115, 0, -10, -25); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); - if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); - r = option.rect.adjusted(imageSpace+115, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); + if(displayDirection=="out") { painter->setPen(penRed); } else { painter->setPen(penGreen); } + r = option.rect.adjusted(imageSpace+450, 5, -10, 0); + painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, displayAmount, &r); font.setBold(false); painter->setFont(font); - } -QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const +QSize TXListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const { - return QSize(200, 50); // very dumb value? + return QSize(600, 30); // very dumb value? } -ListDelegate::~ListDelegate() +TXListDelegate::~TXListDelegate() { } diff --git a/src/qt/txlistdelegate.h b/src/qt/txlistdelegate.h index c1912d979825f..9690565cae067 100644 --- a/src/qt/txlistdelegate.h +++ b/src/qt/txlistdelegate.h @@ -1,14 +1,14 @@ #include #include -class ListDelegate : public QAbstractItemDelegate +class TXListDelegate : public QAbstractItemDelegate { public: - ListDelegate(QObject *parent = 0); + TXListDelegate(QObject *parent = 0); void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; - virtual ~ListDelegate(); + virtual ~TXListDelegate(); }; From 39db7c038fd74e67142ee997e4710009e9621189 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 27 Nov 2014 22:38:34 -0800 Subject: [PATCH 054/141] Fix decimals and direction --- src/qt/txhistorydialog.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 6ccc94ec9f23b..146bfdd68e3c4 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -148,6 +148,9 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : string displayValid; string displayAddress = address; if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } + // clean up trailing zeros - good for RPC not so much for UI + displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos ); + if (displayAmount.length() > 0) { std::string::iterator it = displayAmount.end() - 1; if (*it == '.') { displayAmount.erase(it); } } //get rid of trailing dot if non decimal if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; } if (propertyId < 3) { @@ -160,11 +163,12 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : displayToken = " SPT#" + s; } string displayDirection = "out"; + if (!IsMyAddress(displayAddress)) displayDirection = "in"; QDateTime txTime; txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType)); - qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + " " + displayToken)); + qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + displayToken)); qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection)); qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress)); qItem->setData(Qt::UserRole + 5, txTimeStr); From 053cc91bad94f203afcce5d4d3e7432c747b085f Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sat, 29 Nov 2014 21:51:40 -0800 Subject: [PATCH 055/141] Redo transaction history in to let QT do more of the work --- src/qt/Makefile.am | 1 + src/qt/bitcoin.qrc | 1 + src/qt/forms/txhistorydialog.ui | 2 +- src/qt/res/icons/transaction_invalid.png | Bin 0 -> 3623 bytes src/qt/txhistorydialog.cpp | 117 ++++++++++++++++++++++- src/qt/txhistorydialog.h | 10 +- 6 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 src/qt/res/icons/transaction_invalid.png diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 7ccc07ececf72..901ee643902c6 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -240,6 +240,7 @@ BITCOIN_QT_H = \ winshutdownmonitor.h RES_ICONS = \ + res/icons/transaction_invalid.png \ res/icons/mp_exchange.png \ res/icons/mp_toolbox.png \ res/icons/mp_sp.png \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 17aeab3a42046..5b6f677026275 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,5 +1,6 @@ + res/icons/transaction_invalid.png res/icons/mp_meta_cancelled.png res/icons/mp_meta_filled.png res/icons/mp_meta_open.png diff --git a/src/qt/forms/txhistorydialog.ui b/src/qt/forms/txhistorydialog.ui index d8e48cce8bfb3..941d74c579eda 100644 --- a/src/qt/forms/txhistorydialog.ui +++ b/src/qt/forms/txhistorydialog.ui @@ -20,7 +20,7 @@ 0 - + diff --git a/src/qt/res/icons/transaction_invalid.png b/src/qt/res/icons/transaction_invalid.png new file mode 100644 index 0000000000000000000000000000000000000000..767cd194e3fd850e801c8b534227070b308bf377 GIT binary patch literal 3623 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 literal 0 HcmV?d00001 diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 146bfdd68e3c4..614e6cd7dabf4 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -60,6 +60,7 @@ using namespace leveldb; #include #include #include +#include #include "txlistdelegate.h" @@ -70,8 +71,36 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : { ui->setupUi(this); this->model = model; - ui->txHistoryLW->setItemDelegate(new TXListDelegate(ui->txHistoryLW)); + // setup + ui->txHistoryTable->setColumnCount(5); + ui->txHistoryTable->setHorizontalHeaderItem(0, new QTableWidgetItem(" ")); + ui->txHistoryTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Date")); + ui->txHistoryTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Type")); + ui->txHistoryTable->setHorizontalHeaderItem(3, new QTableWidgetItem("Address")); + ui->txHistoryTable->setHorizontalHeaderItem(4, new QTableWidgetItem("Amount")); + ui->txHistoryTable->verticalHeader()->setVisible(false); +// ui->txHistoryTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); +// ui->txHistoryTable->setShowGrid(false); + ui->txHistoryTable->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->txHistoryTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->txHistoryTable->setSelectionMode(QAbstractItemView::SingleSelection); + ui->txHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); + ui->txHistoryTable->setColumnWidth(0, 23); + ui->txHistoryTable->setColumnWidth(1, 150); + ui->txHistoryTable->setColumnWidth(2, 130); + ui->txHistoryTable->setColumnWidth(4, 200); + + // Always show scroll bar + //ui->txHistoryTable->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + ui->txHistoryTable->setTabKeyNavigation(false); + //view->setContextMenuPolicy(Qt::CustomContextMenu); + + UpdateHistory(); +} + +void TXHistoryDialog::UpdateHistory() +{ CWallet *wallet = pwalletMain; string sAddress = ""; string addressParam = ""; @@ -89,6 +118,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); // iterate backwards + int rowcount = 0; for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; @@ -142,7 +172,30 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : } QListWidgetItem *qItem = new QListWidgetItem(); qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); - string displayType = MPTxType; + // shrink tx type + string displayType = "Unknown"; + switch (mp_obj.getType()) + { + case MSC_TYPE_SIMPLE_SEND: displayType = "Send"; break; + case MSC_TYPE_RESTRICTED_SEND: displayType = "Rest. Send"; break; + case MSC_TYPE_SEND_TO_OWNERS: displayType = "Send To Owners"; break; + case MSC_TYPE_SAVINGS_MARK: displayType = "Mark Savings"; break; + case MSC_TYPE_SAVINGS_COMPROMISED: ; displayType = "Lock Savings"; break; + case MSC_TYPE_RATELIMITED_MARK: displayType = "Rate Limit"; break; + case MSC_TYPE_AUTOMATIC_DISPENSARY: displayType = "Auto Dispense"; break; + case MSC_TYPE_TRADE_OFFER: displayType = "DEx Trade"; break; + case MSC_TYPE_METADEX: displayType = "MetaDEx Trade"; break; + case MSC_TYPE_ACCEPT_OFFER_BTC: displayType = "DEx Accept"; break; + case MSC_TYPE_CREATE_PROPERTY_FIXED: displayType = "Create Property"; break; + case MSC_TYPE_CREATE_PROPERTY_VARIABLE: displayType = "Create Property"; break; + case MSC_TYPE_PROMOTE_PROPERTY: displayType = "Promo Property"; + case MSC_TYPE_CLOSE_CROWDSALE: displayType = "Close Crowdsale"; + case MSC_TYPE_CREATE_PROPERTY_MANUAL: displayType = "Create Property"; break; + case MSC_TYPE_GRANT_PROPERTY_TOKENS: displayType = "Grant Tokens"; break; + case MSC_TYPE_REVOKE_PROPERTY_TOKENS: displayType = "Revoke Tokens"; break; + case MSC_TYPE_CHANGE_ISSUER_ADDRESS: displayType = "Change Issuer"; break; + } + string displayAmount; string displayToken; string displayValid; @@ -167,13 +220,71 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : QDateTime txTime; txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + if (IsMyAddress(displayAddress)) displayAmount = "-" + displayAmount; + //icon + QIcon ic = QIcon(":/icons/transaction_0"); + int confirmations = 1 + GetHeight() - pBlockIndex->nHeight; + switch(confirmations) + { + case 1: ic = QIcon(":/icons/transaction_1"); + case 2: ic = QIcon(":/icons/transaction_2"); + case 3: ic = QIcon(":/icons/transaction_3"); + case 4: ic = QIcon(":/icons/transaction_4"); + case 5: ic = QIcon(":/icons/transaction_5"); + } + if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); + if (!valid) ic = QIcon(":/icons/transaction_invalid"); + + // add to history + ui->txHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); + QTableWidgetItem *typeCell = new QTableWidgetItem(QString::fromStdString(displayType)); + QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); + QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + iconCell->setIcon(ic); + addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); + addressCell->setForeground(QColor("#707070")); + amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountCell->setForeground(QColor("#00AA00")); + if (IsMyAddress(displayAddress)) amountCell->setForeground(QColor("#EE0000")); + if (rowcount % 2) + { + amountCell->setBackground(QColor("#F0F0F0")); + addressCell->setBackground(QColor("#F0F0F0")); + dateCell->setBackground(QColor("#F0F0F0")); + typeCell->setBackground(QColor("#F0F0F0")); + + } + ui->txHistoryTable->setItem(rowcount, 0, iconCell); + ui->txHistoryTable->setItem(rowcount, 1, dateCell); + ui->txHistoryTable->setItem(rowcount, 2, typeCell); + ui->txHistoryTable->setItem(rowcount, 3, addressCell); + ui->txHistoryTable->setItem(rowcount, 4, amountCell); + +/* + if(pending) + { + QFont font; + font.setBold(true); + ui->sellList->item(rowcount, 0)->setFont(font); + ui->sellList->item(rowcount, 1)->setFont(font); + ui->sellList->item(rowcount, 2)->setFont(font); + } +*/ + rowcount += 1; + +/* + + qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType)); qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + displayToken)); qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection)); qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress)); qItem->setData(Qt::UserRole + 5, txTimeStr); qItem->setData(Qt::UserRole + 6, QString::fromStdString(displayValid)); - ui->txHistoryLW->addItem(qItem); +*/ +// ui->txHistoryLW->addItem(qItem); } } } diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index ae438648a1e82..f1869d4b9b140 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -9,7 +9,7 @@ #include #include - +#include class OptionsModel; QT_BEGIN_NAMESPACE @@ -29,11 +29,15 @@ class TXHistoryDialog : public QDialog //void FullRefresh(); explicit TXHistoryDialog(QWidget *parent = 0); void setModel(WalletModel *model); - + void UpdateHistory(); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ QWidget *setupTabChain(QWidget *prev); - + QTableWidgetItem *iconCell; + QTableWidgetItem *dateCell; + QTableWidgetItem *typeCell; + QTableWidgetItem *amountCell; + QTableWidgetItem *addressCell; public slots: //void switchButtonClicked(); From ee2e5b83d940f8fd276fee7f77b05d46db56fe9e Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sat, 29 Nov 2014 22:05:21 -0800 Subject: [PATCH 056/141] Add right click contextual menu to tx history --- src/qt/Makefile.am | 3 -- src/qt/txhistorydialog.cpp | 63 +++++++++++++++++++++++++- src/qt/txhistorydialog.h | 8 +++- src/qt/txlistdelegate.cpp | 91 -------------------------------------- src/qt/txlistdelegate.h | 14 ------ 5 files changed, 68 insertions(+), 111 deletions(-) delete mode 100644 src/qt/txlistdelegate.cpp delete mode 100644 src/qt/txlistdelegate.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 901ee643902c6..1a4e77e1d0bd1 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -145,7 +145,6 @@ QT_MOC_CPP = \ moc_metadexdialog.cpp \ moc_orderhistorydialog.cpp \ moc_txhistorydialog.cpp \ - moc_txlistdelegate.cpp \ moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ moc_lookupaddressdialog.cpp \ @@ -221,7 +220,6 @@ BITCOIN_QT_H = \ lookupspdialog.h \ lookupaddressdialog.h \ orderlistdelegate.h \ - txlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ trafficgraphwidget.h \ @@ -343,7 +341,6 @@ BITCOIN_QT_CPP += \ orderhistorydialog.cpp \ txhistorydialog.cpp \ orderlistdelegate.cpp \ - txlistdelegate.cpp \ lookupspdialog.cpp \ lookupaddressdialog.cpp \ signverifymessagedialog.cpp \ diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 614e6cd7dabf4..3c80ec1c9b4c1 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -61,8 +61,7 @@ using namespace leveldb; #include #include #include - -#include "txlistdelegate.h" +#include TXHistoryDialog::TXHistoryDialog(QWidget *parent) : QDialog(parent), @@ -96,6 +95,29 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : ui->txHistoryTable->setTabKeyNavigation(false); //view->setContextMenuPolicy(Qt::CustomContextMenu); + ui->txHistoryTable->setContextMenuPolicy(Qt::CustomContextMenu); + + // Actions + QAction *copyAddressAction = new QAction(tr("Copy address"), this); + QAction *copyAmountAction = new QAction(tr("Copy amount"), this); + QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this); + QAction *showDetailsAction = new QAction(tr("Show transaction details"), this); + + contextMenu = new QMenu(); + contextMenu->addAction(copyAddressAction); + contextMenu->addAction(copyAmountAction); + contextMenu->addAction(copyTxIDAction); + contextMenu->addAction(showDetailsAction); + + // Connect actions + connect(ui->txHistoryTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); + connect(ui->txHistoryTable, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); + connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); + connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); + connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID())); + connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); + + UpdateHistory(); } @@ -314,3 +336,40 @@ void TXHistoryDialog::setModel(WalletModel *model) //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); } +void TXHistoryDialog::contextualMenu(const QPoint &point) +{ + QModelIndex index = ui->txHistoryTable->indexAt(point); + if(index.isValid()) + { + contextMenu->exec(QCursor::pos()); + } +} + +void TXHistoryDialog::copyAddress() +{ +// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole); +} + +void TXHistoryDialog::copyAmount() +{ +// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole); +} + +void TXHistoryDialog::copyTxID() +{ +// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxIDRole); +} + +void TXHistoryDialog::showDetails() +{ +/* + if(!transactionView->selectionModel()) + return; + QModelIndexList selection = transactionView->selectionModel()->selectedRows(); + if(!selection.isEmpty()) + { + TransactionDescDialog dlg(selection.at(0)); + dlg.exec(); + } +*/ +} diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index f1869d4b9b140..dbbbbf8257ad9 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -45,11 +45,17 @@ public slots: private: Ui::txHistoryDialog *ui; WalletModel *model; + QMenu *contextMenu; private slots: - //void buyRecalc(); + void contextualMenu(const QPoint &); + void showDetails(); + void copyAddress(); + void copyAmount(); + void copyTxID(); signals: + void doubleClicked(const QModelIndex&); // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); }; diff --git a/src/qt/txlistdelegate.cpp b/src/qt/txlistdelegate.cpp deleted file mode 100644 index b54292ddb8eb9..0000000000000 --- a/src/qt/txlistdelegate.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "txlistdelegate.h" - -TXListDelegate::TXListDelegate(QObject *parent) -{ - -} - -void TXListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const -{ - QRect r = option.rect; - QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); - QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); - painter->setPen(linePen); - - // alt the colors - painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); - painter->drawRect(r); - // draw border - painter->setPen(linePen); - painter->drawLine(r.topLeft(),r.topRight()); - painter->drawLine(r.topRight(),r.bottomRight()); - painter->drawLine(r.bottomLeft(),r.bottomRight()); - painter->drawLine(r.topLeft(),r.bottomLeft()); - painter->setPen(fontPen); - - // prepare the data for the entry -// QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); -// string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = "ADDR: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; - txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; -// txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); - QString displayType = index.data(Qt::UserRole + 1).toString(); - QString displayAmount = index.data(Qt::UserRole + 2).toString(); - QString displayDirection = index.data(Qt::UserRole + 3).toString(); - QString displayAddress = index.data(Qt::UserRole + 4).toString(); - QString txTimeText = index.data(Qt::UserRole + 5).toString(); - - // add the appropriate status icon - int imageSpace = 10; - QIcon ic = QIcon(":/icons/meta_cancelled"); - if (!ic.isNull()) - { - r = option.rect.adjusted(5, 10, -10, -10); - ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 30; - } - - // setup pens - QPen penBlack(QColor("#000000")); - QPen penRed(QColor("#CC0000")); - QPen penGreen(QColor("#00AA00")); - QPen penGrey(QColor("#606060")); - - QFont font = painter->font(); - // add the datetime - painter->setPen(penGrey); -// font.setItalic(true); - painter->setFont(font); - r = option.rect.adjusted(imageSpace, 5, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txTimeText, &r); - // add the displaytype - painter->setPen(penBlack); - r = option.rect.adjusted(imageSpace+125, 5, -10, 0); -// font.setBold(true); - font.setItalic(false); - painter->setFont(font); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayType, &r); - // add the address - painter->setPen(penGrey); - font.setBold(false); - painter->setFont(font); - r = option.rect.adjusted(imageSpace+250, 5, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, displayAddress, &r); - // add the amount - font.setBold(true); - painter->setFont(font); - if(displayDirection=="out") { painter->setPen(penRed); } else { painter->setPen(penGreen); } - r = option.rect.adjusted(imageSpace+450, 5, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, displayAmount, &r); - font.setBold(false); - painter->setFont(font); -} - -QSize TXListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const -{ - return QSize(600, 30); // very dumb value? -} - -TXListDelegate::~TXListDelegate() -{ -} diff --git a/src/qt/txlistdelegate.h b/src/qt/txlistdelegate.h deleted file mode 100644 index 9690565cae067..0000000000000 --- a/src/qt/txlistdelegate.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -class TXListDelegate : public QAbstractItemDelegate -{ - public: - TXListDelegate(QObject *parent = 0); - - void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; - QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; - - virtual ~TXListDelegate(); - -}; From 1c3ded5e3821b2f1868f3a8ba0803aa420511589 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sat, 29 Nov 2014 22:20:17 -0800 Subject: [PATCH 057/141] Fix copy handlers and add invisible txid --- src/qt/txhistorydialog.cpp | 14 ++++++++------ src/qt/txhistorydialog.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 3c80ec1c9b4c1..b32e8c26ae847 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -72,7 +72,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : this->model = model; // setup - ui->txHistoryTable->setColumnCount(5); + ui->txHistoryTable->setColumnCount(6); ui->txHistoryTable->setHorizontalHeaderItem(0, new QTableWidgetItem(" ")); ui->txHistoryTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Date")); ui->txHistoryTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Type")); @@ -89,6 +89,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : ui->txHistoryTable->setColumnWidth(1, 150); ui->txHistoryTable->setColumnWidth(2, 130); ui->txHistoryTable->setColumnWidth(4, 200); + ui->txHistoryTable->setColumnWidth(5, 0); // Always show scroll bar //ui->txHistoryTable->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); @@ -264,6 +265,7 @@ void TXHistoryDialog::UpdateHistory() QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); iconCell->setIcon(ic); addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); addressCell->setForeground(QColor("#707070")); @@ -276,14 +278,14 @@ void TXHistoryDialog::UpdateHistory() addressCell->setBackground(QColor("#F0F0F0")); dateCell->setBackground(QColor("#F0F0F0")); typeCell->setBackground(QColor("#F0F0F0")); - + txidCell->setBackground(QColor("#F0F0F0")); } ui->txHistoryTable->setItem(rowcount, 0, iconCell); ui->txHistoryTable->setItem(rowcount, 1, dateCell); ui->txHistoryTable->setItem(rowcount, 2, typeCell); ui->txHistoryTable->setItem(rowcount, 3, addressCell); ui->txHistoryTable->setItem(rowcount, 4, amountCell); - + ui->txHistoryTable->setItem(rowcount, 5, txidCell); /* if(pending) { @@ -347,17 +349,17 @@ void TXHistoryDialog::contextualMenu(const QPoint &point) void TXHistoryDialog::copyAddress() { -// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole); + GUIUtil::setClipboard(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),3)->text()); } void TXHistoryDialog::copyAmount() { -// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole); + GUIUtil::setClipboard(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),4)->text()); } void TXHistoryDialog::copyTxID() { -// GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxIDRole); + GUIUtil::setClipboard(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),5)->text()); } void TXHistoryDialog::showDetails() diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index dbbbbf8257ad9..fd460e3e1f83a 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -38,6 +38,7 @@ class TXHistoryDialog : public QDialog QTableWidgetItem *typeCell; QTableWidgetItem *amountCell; QTableWidgetItem *addressCell; + QTableWidgetItem *txidCell; public slots: //void switchButtonClicked(); From f5f206e0e472e85d8e3891aca8c4442f34de2ee7 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 00:16:56 -0800 Subject: [PATCH 058/141] Completing tx history --- src/Makefile.am | 1 + src/mastercore_rpc.cpp | 3 +- src/qt/txhistorydialog.cpp | 69 +++++++++++++++++++++++++++++++++----- src/qt/txhistorydialog.h | 8 +++++ 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 895fe208aab6e..96994bc31bbfe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,7 @@ BITCOIN_CORE_H = \ mastercore_parse_string.h \ mastercore_tx.h \ mastercore_dex.h \ + mastercore_rpc.h \ mastercore_sp.h \ mastercore_errors.h \ crypter.h \ diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 7924cbd80c740..339fea3561d4f 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -40,6 +40,7 @@ using namespace mastercore; #include "mastercore_tx.h" #include "mastercore_sp.h" #include "mastercore_errors.h" +#include "mastercore_rpc.h" void MetaDexObjectToJSON(const CMPMetaDEx& obj, Object& metadex_obj) { @@ -1369,7 +1370,7 @@ Value listblocktransactions_MP(const Array& params, bool fHelp) } // this function standardizes the RPC output for gettransaction_MP and listtransaction_MP into a central function -static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filterAddress = "") +int populateRPCTransactionObject(uint256 txid, Object *txobj, string filterAddress = "") { //uint256 hash; //hash.SetHex(params[0].get_str()); diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index b32e8c26ae847..4e84943d8cb3f 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -54,6 +54,7 @@ using namespace leveldb; #include "mastercore_dex.h" #include "mastercore_tx.h" #include "mastercore_sp.h" +#include "mastercore_rpc.h" #include "mastercore_parse_string.h" #include @@ -62,6 +63,7 @@ using namespace leveldb; #include #include #include +#include TXHistoryDialog::TXHistoryDialog(QWidget *parent) : QDialog(parent), @@ -364,14 +366,65 @@ void TXHistoryDialog::copyTxID() void TXHistoryDialog::showDetails() { -/* - if(!transactionView->selectionModel()) - return; - QModelIndexList selection = transactionView->selectionModel()->selectedRows(); - if(!selection.isEmpty()) + Object txobj; + uint256 txid; + txid.SetHex(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),5)->text().toStdString()); + int pop = populateRPCTransactionObject(txid, &txobj, ""); + std::string strTXText = write_string(Value(txobj), false) + "\n"; + // clean up + string from = ","; + string to = ",\n "; + size_t start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) { - TransactionDescDialog dlg(selection.at(0)); - dlg.exec(); + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' } -*/ + from = ":"; + to = " : "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "{"; + to = "{\n "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "}"; + to = "\n}"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + + QString txText = QString::fromStdString(strTXText); + QDialog *txDlg = new QDialog; + QLayout *dlgLayout = new QVBoxLayout; + dlgLayout->setSpacing(12); + dlgLayout->setMargin(12); + QTextEdit *dlgTextEdit = new QTextEdit; + dlgTextEdit->setText(txText); + dlgTextEdit->setStatusTip("Transaction Information"); + dlgLayout->addWidget(dlgTextEdit); + txDlg->setWindowTitle("Transaction Information"); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + dlgLayout->addWidget(buttonBox); + txDlg->setLayout(dlgLayout); + txDlg->resize(700, 360); + connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); + txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed + if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close +} + +void TXHistoryDialog::accept() +{ + } diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index fd460e3e1f83a..9802904a74d0f 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -10,6 +10,9 @@ #include #include #include +#include +#include + class OptionsModel; QT_BEGIN_NAMESPACE @@ -30,8 +33,10 @@ class TXHistoryDialog : public QDialog explicit TXHistoryDialog(QWidget *parent = 0); void setModel(WalletModel *model); void UpdateHistory(); + void accept(); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ + QDialog *txDlg; QWidget *setupTabChain(QWidget *prev); QTableWidgetItem *iconCell; QTableWidgetItem *dateCell; @@ -39,6 +44,9 @@ class TXHistoryDialog : public QDialog QTableWidgetItem *amountCell; QTableWidgetItem *addressCell; QTableWidgetItem *txidCell; + QLayout *dlgLayout; + QTextEdit *dlgTextEdit; + QDialogButtonBox *buttonBox; public slots: //void switchButtonClicked(); From 31045851aa2e947d31471f705e850e93f17a51a2 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 00:20:17 -0800 Subject: [PATCH 059/141] Missing new mastercore_rpc.h file --- src/mastercore_rpc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/mastercore_rpc.h diff --git a/src/mastercore_rpc.h b/src/mastercore_rpc.h new file mode 100644 index 0000000000000..862841ad338b1 --- /dev/null +++ b/src/mastercore_rpc.h @@ -0,0 +1,10 @@ +#ifndef _MASTERCORE_RPC +#define _MASTERCORE_RPC + +#include "mastercore.h" + +int populateRPCTransactionObject(uint256 txid, Object *txobj, string filterAddress); + +#endif // #ifndef _MASTERCORE_RPC + + From d2ca9e9292cd358fd5c90823fd8b3942185c6ce0 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 00:34:28 -0800 Subject: [PATCH 060/141] Fix addresses and send/receive verbage --- src/qt/txhistorydialog.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 4e84943d8cb3f..ff3cda8ca2d68 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -168,7 +168,8 @@ void TXHistoryDialog::UpdateHistory() string statusText; unsigned int propertyId = 0; uint64_t amount = 0; - string address; + string senderAddress; + string refAddress; bool divisible = false; bool valid = false; string MPTxType; @@ -180,8 +181,8 @@ void TXHistoryDialog::UpdateHistory() if (0<=mp_obj.step1()) { MPTxType = mp_obj.getTypeString(); - address = mp_obj.getSender(); - + senderAddress = mp_obj.getSender(); + refAddress = mp_obj.getReceiver(); int tmpblock=0; uint32_t tmptype=0; uint64_t amountNew=0; @@ -224,7 +225,8 @@ void TXHistoryDialog::UpdateHistory() string displayAmount; string displayToken; string displayValid; - string displayAddress = address; + string displayAddress; + if (IsMyAddress(senderAddress)) { displayAddress = senderAddress; } else { displayAddress = refAddress; } if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } // clean up trailing zeros - good for RPC not so much for UI displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos ); @@ -241,11 +243,12 @@ void TXHistoryDialog::UpdateHistory() displayToken = " SPT#" + s; } string displayDirection = "out"; - if (!IsMyAddress(displayAddress)) displayDirection = "in"; + if ((displayType == "Send") && (!IsMyAddress(senderAddress))) { displayType = "Receive"; } + QDateTime txTime; txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); - if (IsMyAddress(displayAddress)) displayAmount = "-" + displayAmount; + if (IsMyAddress(senderAddress)) displayAmount = "-" + displayAmount; //icon QIcon ic = QIcon(":/icons/transaction_0"); int confirmations = 1 + GetHeight() - pBlockIndex->nHeight; @@ -273,7 +276,7 @@ void TXHistoryDialog::UpdateHistory() addressCell->setForeground(QColor("#707070")); amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); amountCell->setForeground(QColor("#00AA00")); - if (IsMyAddress(displayAddress)) amountCell->setForeground(QColor("#EE0000")); + if (IsMyAddress(senderAddress)) amountCell->setForeground(QColor("#EE0000")); if (rowcount % 2) { amountCell->setBackground(QColor("#F0F0F0")); From eb44dfbf7b3031211869b60a2de8510641d410b5 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 11:18:45 -0800 Subject: [PATCH 061/141] Fix double click on tx history and clean up a bit --- src/qt/forms/lookupspdialog.ui | 4 ++-- src/qt/lookupaddressdialog.cpp | 5 ++++- src/qt/lookupspdialog.cpp | 7 ++++++- src/qt/txhistorydialog.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui index 34b1000c5e9fb..5270a059d9106 100644 --- a/src/qt/forms/lookupspdialog.ui +++ b/src/qt/forms/lookupspdialog.ui @@ -120,7 +120,7 @@ 0 - + QFrame::StyledPanel @@ -353,7 +353,7 @@ - + QFrame::StyledPanel diff --git a/src/qt/lookupaddressdialog.cpp b/src/qt/lookupaddressdialog.cpp index fd126c47bd64b..c33eab37c47ee 100644 --- a/src/qt/lookupaddressdialog.cpp +++ b/src/qt/lookupaddressdialog.cpp @@ -83,6 +83,7 @@ LookupAddressDialog::LookupAddressDialog(QWidget *parent) : balances[pItem-1]->setVisible(false); } ui->onlyLabel->setVisible(false); + ui->frame->setVisible(false); } void LookupAddressDialog::searchAddress() @@ -102,7 +103,7 @@ void LookupAddressDialog::searchAddress() ui->addressLabel->setText(QString::fromStdString(searchText)); if ((searchText.substr(0,1) == "1") || (searchText.substr(0,1) == "m") || (searchText.substr(0,1) == "n")) ui->addressTypeLabel->setText("Public Key Hash"); if ((searchText.substr(0,1) == "2") || (searchText.substr(0,1) == "3")) ui->addressTypeLabel->setText("Pay to Script Hash"); - if (IsMyAddress(searchText)) { ui->isMineLabel->setText("True"); } else { ui->isMineLabel->setText("False"); } + if (IsMyAddress(searchText)) { ui->isMineLabel->setText("Yes"); } else { ui->isMineLabel->setText("No"); } //scrappy way to do this, find a more efficient way of interacting with labels //show first 10 SPs with balances - needs to be converted to listwidget or something @@ -157,6 +158,7 @@ void LookupAddressDialog::searchAddress() } // set balance info + ui->frame->setVisible(true); QLabel* balances[] = { ui->propertyLabel1, ui->propertyLabel2, ui->propertyLabel3, ui->propertyLabel4, ui->propertyLabel5, ui->propertyLabel6, ui->propertyLabel7, ui->propertyLabel8, ui->propertyLabel9, ui->propertyLabel10 }; QLabel* labels[] = { ui->property1, ui->property2, ui->property3, ui->property4, ui->property5, ui->property6, ui->property7, ui->property8, ui->property9, ui->property10 }; for (pItem = 1; pItem < 11; pItem++) @@ -202,6 +204,7 @@ void LookupAddressDialog::searchAddress() ui->addressLabel->setText("N/A"); ui->addressTypeLabel->setText("N/A"); ui->isMineLabel->setText("N/A"); + ui->frame->setVisible(false); // show error message string strText = "The address entered was not valid."; QString strQText = QString::fromStdString(strText); diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp index 7cf35e5440e26..a3b70a32af21c 100644 --- a/src/qt/lookupspdialog.cpp +++ b/src/qt/lookupspdialog.cpp @@ -88,6 +88,9 @@ LookupSPDialog::LookupSPDialog(QWidget *parent) : ui->issuerPercLabel->setVisible(false); ui->activeLabel->setVisible(false); ui->active->setText("Not applicable."); + ui->topFrame->setVisible(false); + ui->leftFrame->setVisible(false); + ui->rightFrame->setVisible(false); } void LookupSPDialog::searchSP() @@ -339,7 +342,9 @@ void LookupSPDialog::updateDisplayedProperty() ui->activeLabel->setVisible(false); ui->active->setText("Not applicable."); } - + ui->topFrame->setVisible(true); + ui->leftFrame->setVisible(true); + ui->rightFrame->setVisible(true); } void LookupSPDialog::searchButtonClicked() diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index ff3cda8ca2d68..119fa20aae76b 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -114,7 +114,7 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : // Connect actions connect(ui->txHistoryTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); - connect(ui->txHistoryTable, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); + connect(ui->txHistoryTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails())); connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID())); From d778f80fa8fc4573b58f791a89b587d36df35265 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 11:26:35 -0800 Subject: [PATCH 062/141] Rename OK to Close in tx dialog and clean up more --- src/qt/txhistorydialog.cpp | 27 ++++----------------------- src/qt/txhistorydialog.h | 2 ++ 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 119fa20aae76b..62eddda7958bc 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -291,29 +291,7 @@ void TXHistoryDialog::UpdateHistory() ui->txHistoryTable->setItem(rowcount, 3, addressCell); ui->txHistoryTable->setItem(rowcount, 4, amountCell); ui->txHistoryTable->setItem(rowcount, 5, txidCell); -/* - if(pending) - { - QFont font; - font.setBold(true); - ui->sellList->item(rowcount, 0)->setFont(font); - ui->sellList->item(rowcount, 1)->setFont(font); - ui->sellList->item(rowcount, 2)->setFont(font); - } -*/ rowcount += 1; - -/* - - - qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType)); - qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + displayToken)); - qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection)); - qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress)); - qItem->setData(Qt::UserRole + 5, txTimeStr); - qItem->setData(Qt::UserRole + 6, QString::fromStdString(displayValid)); -*/ -// ui->txHistoryLW->addItem(qItem); } } } @@ -418,7 +396,10 @@ void TXHistoryDialog::showDetails() dlgTextEdit->setStatusTip("Transaction Information"); dlgLayout->addWidget(dlgTextEdit); txDlg->setWindowTitle("Transaction Information"); - QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + QPushButton *closeButton = new QPushButton(tr("&Close")); + closeButton->setDefault(true); + QDialogButtonBox *buttonBox = new QDialogButtonBox; + buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); dlgLayout->addWidget(buttonBox); txDlg->setLayout(dlgLayout); txDlg->resize(700, 360); diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index 9802904a74d0f..1e87c79a3bc23 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -12,6 +12,7 @@ #include #include #include +#include class OptionsModel; @@ -47,6 +48,7 @@ class TXHistoryDialog : public QDialog QLayout *dlgLayout; QTextEdit *dlgTextEdit; QDialogButtonBox *buttonBox; + QPushButton *closeButton; public slots: //void switchButtonClicked(); From ae66f65a57768b0ce8279d1761a9e4cf6c1d2cad Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 11:31:44 -0800 Subject: [PATCH 063/141] Add limit of 50 historical transactions as unsure of performance --- src/qt/txhistorydialog.cpp | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 62eddda7958bc..0c6e448ab8ff1 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -130,8 +130,7 @@ void TXHistoryDialog::UpdateHistory() string sAddress = ""; string addressParam = ""; - int64_t nCount = 10; - int64_t nFrom = 0; + int64_t nCount = 50; //don't display more than 50 historical transactions at the moment until we can move to a cached model int64_t nStartBlock = 0; int64_t nEndBlock = 999999; @@ -294,25 +293,9 @@ void TXHistoryDialog::UpdateHistory() rowcount += 1; } } + // don't burn time doing more work than we need to + if (rowcount > nCount) break; } - // don't burn time doing more work than we need to -// if ((int)response.size() >= (nCount+nFrom)) break; - // sort array here and cut on nFrom and nCount -// if (nFrom > (int)response.size()) -// nFrom = response.size(); -// if ((nFrom + nCount) > (int)response.size()) -// nCount = response.size() - nFrom; -// Array::iterator first = response.begin(); -// std::advance(first, nFrom); -// Array::iterator last = response.begin(); -// std::advance(last, nFrom+nCount); - -// if (last != response.end()) response.erase(last, response.end()); -// if (first != response.begin()) response.erase(response.begin(), first); - -// std::reverse(response.begin(), response.end()); // return oldest to newest? - // return response; // return response array for JSON serialization - } void TXHistoryDialog::setModel(WalletModel *model) From 8f0a7037a8fe24ccc2c0ac4a9698d8028b8eee8b Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 11:35:30 -0800 Subject: [PATCH 064/141] fix build errors --- src/qt/txhistorydialog.cpp | 109 +++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 0c6e448ab8ff1..87262ce92a04d 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -334,61 +334,64 @@ void TXHistoryDialog::showDetails() uint256 txid; txid.SetHex(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),5)->text().toStdString()); int pop = populateRPCTransactionObject(txid, &txobj, ""); - std::string strTXText = write_string(Value(txobj), false) + "\n"; - // clean up - string from = ","; - string to = ",\n "; - size_t start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + if (0<=pop) { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = ":"; - to = " : "; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "{"; - to = "{\n "; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "}"; - to = "\n}"; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } + std::string strTXText = write_string(Value(txobj), false) + "\n"; + // clean up + string from = ","; + string to = ",\n "; + size_t start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = ":"; + to = " : "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "{"; + to = "{\n "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "}"; + to = "\n}"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } - QString txText = QString::fromStdString(strTXText); - QDialog *txDlg = new QDialog; - QLayout *dlgLayout = new QVBoxLayout; - dlgLayout->setSpacing(12); - dlgLayout->setMargin(12); - QTextEdit *dlgTextEdit = new QTextEdit; - dlgTextEdit->setText(txText); - dlgTextEdit->setStatusTip("Transaction Information"); - dlgLayout->addWidget(dlgTextEdit); - txDlg->setWindowTitle("Transaction Information"); - QPushButton *closeButton = new QPushButton(tr("&Close")); - closeButton->setDefault(true); - QDialogButtonBox *buttonBox = new QDialogButtonBox; - buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); - dlgLayout->addWidget(buttonBox); - txDlg->setLayout(dlgLayout); - txDlg->resize(700, 360); - connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); - txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed - if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close + QString txText = QString::fromStdString(strTXText); + QDialog *txDlg = new QDialog; + QLayout *dlgLayout = new QVBoxLayout; + dlgLayout->setSpacing(12); + dlgLayout->setMargin(12); + QTextEdit *dlgTextEdit = new QTextEdit; + dlgTextEdit->setText(txText); + dlgTextEdit->setStatusTip("Transaction Information"); + dlgLayout->addWidget(dlgTextEdit); + txDlg->setWindowTitle("Transaction Information"); + QPushButton *closeButton = new QPushButton(tr("&Close")); + closeButton->setDefault(true); + QDialogButtonBox *buttonBox = new QDialogButtonBox; + buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); + dlgLayout->addWidget(buttonBox); + txDlg->setLayout(dlgLayout); + txDlg->resize(700, 360); + connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); + txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed + if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close + } } void TXHistoryDialog::accept() From f877b90db08aa911f808f762fe6d7d0b0fb9d8d6 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 12:15:50 -0800 Subject: [PATCH 065/141] Add QR support to address lookup in toolbox --- src/qt/forms/lookupaddressdialog.ui | 58 ++++++++++++++- src/qt/lookupaddressdialog.cpp | 109 +++++++++++++++++++++++++++- src/qt/lookupaddressdialog.h | 27 ++++++- 3 files changed, 187 insertions(+), 7 deletions(-) diff --git a/src/qt/forms/lookupaddressdialog.ui b/src/qt/forms/lookupaddressdialog.ui index 86a643ab7334e..9eb96824d205f 100644 --- a/src/qt/forms/lookupaddressdialog.ui +++ b/src/qt/forms/lookupaddressdialog.ui @@ -133,15 +133,37 @@ - + 0 - + + + + 0 + 0 + + + + + 96 + 96 + + + + QRCode + + + + + QFormLayout::AllNonFixedFieldsGrow + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + 0 @@ -201,7 +223,30 @@ - Key In Wallet: + In Wallet: + + + + + + + Balance: + + + + + + + + 75 + true + + + + N/A + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -209,6 +254,13 @@ + + + + 0 + + + diff --git a/src/qt/lookupaddressdialog.cpp b/src/qt/lookupaddressdialog.cpp index c33eab37c47ee..e01c2093d133e 100644 --- a/src/qt/lookupaddressdialog.cpp +++ b/src/qt/lookupaddressdialog.cpp @@ -59,6 +59,84 @@ using namespace leveldb; #include #include +#include +#include +#include +#include +#include +#include +#if QT_VERSION < 0x050000 +#include +#endif + +#if defined(HAVE_CONFIG_H) +#include "bitcoin-config.h" /* for USE_QRCODE */ +#endif + +#ifdef USE_QRCODE +#include +#endif + +MPQRImageWidget::MPQRImageWidget(QWidget *parent): + QLabel(parent), contextMenu(0) +{ + contextMenu = new QMenu(); + QAction *saveImageAction = new QAction(tr("&Save Image..."), this); + connect(saveImageAction, SIGNAL(triggered()), this, SLOT(saveImage())); + contextMenu->addAction(saveImageAction); + QAction *copyImageAction = new QAction(tr("&Copy Image"), this); + connect(copyImageAction, SIGNAL(triggered()), this, SLOT(copyImage())); + contextMenu->addAction(copyImageAction); +} + +QImage MPQRImageWidget::exportImage() +{ + if(!pixmap()) + return QImage(); + return pixmap()->toImage().scaled(256,256); +} + +void MPQRImageWidget::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton && pixmap()) + { + event->accept(); + QMimeData *mimeData = new QMimeData; + mimeData->setImageData(exportImage()); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->exec(); + } else { + QLabel::mousePressEvent(event); + } +} + +void MPQRImageWidget::saveImage() +{ + if(!pixmap()) + return; + QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), NULL); + if (!fn.isEmpty()) + { + exportImage().save(fn); + } +} + +void MPQRImageWidget::copyImage() +{ + if(!pixmap()) + return; + QApplication::clipboard()->setImage(exportImage()); +} + +void MPQRImageWidget::contextMenuEvent(QContextMenuEvent *event) +{ + if(!pixmap()) + return; + contextMenu->exec(event->globalPos()); +} + LookupAddressDialog::LookupAddressDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LookupAddressDialog), @@ -104,12 +182,38 @@ void LookupAddressDialog::searchAddress() if ((searchText.substr(0,1) == "1") || (searchText.substr(0,1) == "m") || (searchText.substr(0,1) == "n")) ui->addressTypeLabel->setText("Public Key Hash"); if ((searchText.substr(0,1) == "2") || (searchText.substr(0,1) == "3")) ui->addressTypeLabel->setText("Pay to Script Hash"); if (IsMyAddress(searchText)) { ui->isMineLabel->setText("Yes"); } else { ui->isMineLabel->setText("No"); } + ui->balanceLabel->setText(QString::fromStdString(FormatDivisibleMP(getUserAvailableMPbalance(searchText, 1)) + " MSC")); + // QR + #ifdef USE_QRCODE + ui->QRCode->setText(""); + QRcode *code = QRcode_encodeString(QString::fromStdString(searchText).toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); + if (!code) + { + ui->QRCode->setText(tr("Error encoding address into QR Code.")); + } + else + { + QImage myImage = QImage(code->width + 4, code->width + 4, QImage::Format_RGB32); + myImage.fill(0xffffff); + unsigned char *p = code->data; + for (int y = 0; y < code->width; y++) + { + for (int x = 0; x < code->width; x++) + { + myImage.setPixel(x + 2, y + 2, ((*p & 1) ? 0x0 : 0xffffff)); + p++; + } + } + QRcode_free(code); + ui->QRCode->setPixmap(QPixmap::fromImage(myImage).scaled(96, 96)); + } + #endif //scrappy way to do this, find a more efficient way of interacting with labels //show first 10 SPs with balances - needs to be converted to listwidget or something unsigned int propertyId; - unsigned int lastFoundPropertyIdMainEco = 0; - unsigned int lastFoundPropertyIdTestEco = 0; + unsigned int lastFoundPropertyIdMainEco = 1; + unsigned int lastFoundPropertyIdTestEco = 1; string pName[12]; uint64_t pBal[12]; bool pDivisible[12]; @@ -170,7 +274,6 @@ void LookupAddressDialog::searchAddress() labels[pItem-1]->setText(pName[pItem].c_str()); string tokenLabel = " SPT"; if (pName[pItem]=="Test MasterCoin (#2)") { tokenLabel = " TMSC"; } - if (pName[pItem]=="MasterCoin (#1)") { tokenLabel = " MSC"; } if (pDivisible[pItem]) { balances[pItem-1]->setText(QString::fromStdString(FormatDivisibleMP(pBal[pItem]) + tokenLabel)); diff --git a/src/qt/lookupaddressdialog.h b/src/qt/lookupaddressdialog.h index 8fa9711de4740..eeb30f9515866 100644 --- a/src/qt/lookupaddressdialog.h +++ b/src/qt/lookupaddressdialog.h @@ -9,17 +9,42 @@ #include #include - +#include +#include class OptionsModel; QT_BEGIN_NAMESPACE class QUrl; +class QMenu; QT_END_NAMESPACE namespace Ui { class LookupAddressDialog; } +/* Label widget for QR code. This image can be dragged, dropped, copied and saved + * to disk. + */ +class MPQRImageWidget : public QLabel +{ + Q_OBJECT + +public: + explicit MPQRImageWidget(QWidget *parent = 0); + QImage exportImage(); + +public slots: + void saveImage(); + void copyImage(); + +protected: + virtual void mousePressEvent(QMouseEvent *event); + virtual void contextMenuEvent(QContextMenuEvent *event); + +private: + QMenu *contextMenu; +}; + /** Dialog for looking up Master Protocol address */ class LookupAddressDialog : public QDialog { From 20108cf22df541fcf799e48bf01f71c87a2c7300 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 12:36:53 -0800 Subject: [PATCH 066/141] Add tx lookup to toolbox --- src/qt/Makefile.am | 4 + src/qt/forms/lookuptxdialog.ui | 116 +++++++++++++++++++++ src/qt/lookuptxdialog.cpp | 177 +++++++++++++++++++++++++++++++++ src/qt/lookuptxdialog.h | 58 +++++++++++ src/qt/walletview.cpp | 6 +- src/qt/walletview.h | 2 + 6 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 src/qt/forms/lookuptxdialog.ui create mode 100644 src/qt/lookuptxdialog.cpp create mode 100644 src/qt/lookuptxdialog.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 1a4e77e1d0bd1..82a7361938592 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -106,6 +106,7 @@ QT_FORMS_UI = \ forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/lookupaddressdialog.ui \ + forms/lookuptxdialog.ui \ forms/signverifymessagedialog.ui \ forms/transactiondescdialog.ui @@ -148,6 +149,7 @@ QT_MOC_CPP = \ moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ moc_lookupaddressdialog.cpp \ + moc_lookuptxdialog.cpp \ moc_signverifymessagedialog.cpp \ moc_splashscreen.cpp \ moc_trafficgraphwidget.cpp \ @@ -219,6 +221,7 @@ BITCOIN_QT_H = \ txhistorydialog.h \ lookupspdialog.h \ lookupaddressdialog.h \ + lookuptxdialog.h \ orderlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ @@ -343,6 +346,7 @@ BITCOIN_QT_CPP += \ orderlistdelegate.cpp \ lookupspdialog.cpp \ lookupaddressdialog.cpp \ + lookuptxdialog.cpp \ signverifymessagedialog.cpp \ transactiondesc.cpp \ transactiondescdialog.cpp \ diff --git a/src/qt/forms/lookuptxdialog.ui b/src/qt/forms/lookuptxdialog.ui new file mode 100644 index 0000000000000..bc860ec9af294 --- /dev/null +++ b/src/qt/forms/lookuptxdialog.ui @@ -0,0 +1,116 @@ + + + LookupTXDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + false + + + background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + + + true + + + 3 + + + + + + + 0 + + + + + true + + + + 0 + 0 + + + + Search Transaction: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 8 + + + + + + + + + + Search + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + + + diff --git a/src/qt/lookuptxdialog.cpp b/src/qt/lookuptxdialog.cpp new file mode 100644 index 0000000000000..16cc53e4f55cf --- /dev/null +++ b/src/qt/lookuptxdialog.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "lookuptxdialog.h" +#include "ui_lookuptxdialog.h" + +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes + +using namespace json_spirit; +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" +#include "mastercore_rpc.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#if QT_VERSION < 0x050000 +#include +#endif + +LookupTXDialog::LookupTXDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LookupTXDialog), + model(0) +{ + ui->setupUi(this); + this->model = model; + + // populate placeholder text + ui->searchLineEdit->setPlaceholderText("Search transaction"); + + // connect actions + connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); +} + +void LookupTXDialog::searchTX() +{ + // search function to lookup address + string searchText = ui->searchLineEdit->text().toStdString(); + + // first let's check if we have a searchText, if not do nothing + if (searchText.empty()) return; + + uint256 hash; + hash.SetHex(searchText); + Object txobj; + // make a request to new RPC populator function to populate a transaction object + int populateResult = populateRPCTransactionObject(hash, &txobj, ""); + if (0<=populateResult) + { + std::string strTXText = write_string(Value(txobj), false) + "\n"; + // clean up + string from = ","; + string to = ",\n "; + size_t start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = ":"; + to = " : "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "{"; + to = "{\n "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "}"; + to = "\n}"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + + QString txText = QString::fromStdString(strTXText); + QDialog *txDlg = new QDialog; + QLayout *dlgLayout = new QVBoxLayout; + dlgLayout->setSpacing(12); + dlgLayout->setMargin(12); + QTextEdit *dlgTextEdit = new QTextEdit; + dlgTextEdit->setText(txText); + dlgTextEdit->setStatusTip("Transaction Information"); + dlgLayout->addWidget(dlgTextEdit); + txDlg->setWindowTitle("Transaction Information"); + QPushButton *closeButton = new QPushButton(tr("&Close")); + closeButton->setDefault(true); + QDialogButtonBox *buttonBox = new QDialogButtonBox; + buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); + dlgLayout->addWidget(buttonBox); + txDlg->setLayout(dlgLayout); + txDlg->resize(700, 360); + connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); + txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed + if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close + } + else + { + // show error message + string strText = "The transaction ID entered was not valid."; + QString strQText = QString::fromStdString(strText); + QMessageBox errorDialog; + errorDialog.setIcon(QMessageBox::Critical); + errorDialog.setWindowTitle("TXID error"); + errorDialog.setText(strQText); + errorDialog.setStandardButtons(QMessageBox::Ok); + errorDialog.setDefaultButton(QMessageBox::Ok); + if(errorDialog.exec() == QMessageBox::Ok) { } // no other button to choose, acknowledged + } +} + +void LookupTXDialog::searchButtonClicked() +{ + searchTX(); +} diff --git a/src/qt/lookuptxdialog.h b/src/qt/lookuptxdialog.h new file mode 100644 index 0000000000000..5768aeb8d36df --- /dev/null +++ b/src/qt/lookuptxdialog.h @@ -0,0 +1,58 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef LOOKUPTXDIALOG_H +#define LOOKUPTXDIALOG_H + +#include "walletmodel.h" + +#include +#include +#include +#include +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class LookupTXDialog; +} + +/** Dialog for looking up Master Protocol txns */ +class LookupTXDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LookupTXDialog(QWidget *parent = 0); + void searchTX(); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + QDialog *txDlg; + QLayout *dlgLayout; + QTextEdit *dlgTextEdit; + QDialogButtonBox *buttonBox; + QPushButton *closeButton; + +public slots: + void searchButtonClicked(); + +private: + Ui::LookupTXDialog *ui; + WalletModel *model; + +//private slots: + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // LOOKUPTXDIALOG_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index b64cde1518b37..065565f0a5f6e 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -15,6 +15,7 @@ #include "sendcoinsdialog.h" #include "sendmpdialog.h" #include "lookupspdialog.h" +#include "lookuptxdialog.h" #include "lookupaddressdialog.h" #include "metadexdialog.h" #include "signverifymessagedialog.h" @@ -132,12 +133,11 @@ WalletView::WalletView(QWidget *parent): QVBoxLayout *tvbox = new QVBoxLayout(); addressLookupTab = new LookupAddressDialog(); spLookupTab = new LookupSPDialog(); -// txLookupTab = new LookupTXDialog(); + txLookupTab = new LookupTXDialog(); QTabWidget *tTabHolder = new QTabWidget(); tTabHolder->addTab(addressLookupTab,tr("Lookup Address")); tTabHolder->addTab(spLookupTab,tr("Lookup Property")); -// tTabHolder->addTab(txLookupTab,tr("Lookup Transaction"); - tTabHolder->addTab(new QWidget(),tr("Lookup Transaction")); + tTabHolder->addTab(txLookupTab,tr("Lookup Transaction")); tvbox->addWidget(tTabHolder); toolboxPage->setLayout(tvbox); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 3a228bf4e900e..1973e1fe6c88e 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -15,6 +15,7 @@ class SendCoinsDialog; class SendMPDialog; class OrderHistoryDialog; class LookupSPDialog; +class LookupTXDialog; class LookupAddressDialog; class MetaDExDialog; class SendCoinsRecipient; @@ -73,6 +74,7 @@ class WalletView : public QStackedWidget SendCoinsDialog *sendCoinsTab; SendMPDialog *sendMPTab; LookupSPDialog *spLookupTab; + LookupTXDialog *txLookupTab; LookupAddressDialog *addressLookupTab; OrderHistoryDialog *orderHistoryTab; MetaDExDialog *metaDExTab; From a263a5d94869a8a74b4a67859cc36bb5746ea060 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 19:29:39 -0800 Subject: [PATCH 067/141] More work on history and pending txs --- src/mastercore.cpp | 50 ++++++++++++++++++-- src/mastercore.h | 7 ++- src/qt/txhistorydialog.cpp | 96 ++++++++++++++++++++++++++++++++++++-- src/qt/walletview.cpp | 1 + src/qt/walletview.h | 3 +- 5 files changed, 145 insertions(+), 12 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index a1a7dcfec082e..2f64d1f1db9fc 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -361,7 +361,7 @@ AcceptMap mastercore::my_accepts; CMPSPInfo *mastercore::_my_sps; CrowdMap mastercore::my_crowds; -static PendingMap my_pending; +PendingMap mastercore::my_pending; static CMPPending *pendingDelete(const uint256 txid, bool bErase = false) { @@ -398,11 +398,11 @@ static CMPPending *pendingDelete(const uint256 txid, bool bErase = false) return (CMPPending *) NULL; } -static int pendingAdd(const uint256 &txid, const string &FromAddress, unsigned int propId, int64_t Amount) +static int pendingAdd(const uint256 &txid, const string &FromAddress, unsigned int propId, int64_t Amount, int64_t type, const string &txDesc) { CMPPending pending; - if (msc_debug_verbose3) file_log("%s(%s,%s,%u,%ld), line %d, file: %s\n", __FUNCTION__, txid.GetHex().c_str(), FromAddress.c_str(), propId, Amount, __LINE__, __FILE__); + if (msc_debug_verbose3) file_log("%s(%s,%s,%u,%ld,%d, %s), line %d, file: %s\n", __FUNCTION__, txid.GetHex().c_str(), FromAddress.c_str(), propId, Amount, type, txDesc,__LINE__, __FILE__); // support for pending, 0-confirm if (update_tally_map(FromAddress, propId, -Amount, PENDING)) @@ -410,7 +410,8 @@ CMPPending pending; pending.src = FromAddress; pending.amount = Amount; pending.prop = propId; - + pending.desc = txDesc; + pending.type = type; pending.print(txid); my_pending.insert(std::make_pair(txid, pending)); } @@ -2965,7 +2966,46 @@ const unsigned int prop = PropertyID; if (0 == rc) { - (void) pendingAdd(txid, FromAddress, prop, amount); + // only simple sends and metadex pending needed at moment + Object txobj; + txobj.push_back(Pair("txid", txid.GetHex())); + txobj.push_back(Pair("sendingaddress", FromAddress)); + if (TransactionType == MSC_TYPE_SIMPLE_SEND) txobj.push_back(Pair("referenceaddress", ToAddress)); + txobj.push_back(Pair("confirmations", 0)); + // txobj->push_back(Pair("fee", ValueFromAmount(nFee))); + txobj.push_back(Pair("version", (int64_t)0)); //we only send v0 currently so all pending v0 + txobj.push_back(Pair("type_int", (int64_t)TransactionType)); + bool divisible = false; + bool desiredDivisible = false; + string amountStr; + string amountDStr; + switch (TransactionType) + { + case 0: //simple send + txobj.push_back(Pair("type", "Simple send")); + txobj.push_back(Pair("propertyid", (uint64_t)PropertyID)); + divisible = isPropertyDivisible(PropertyID); + txobj.push_back(Pair("divisible", divisible)); + if (divisible) { amountStr = FormatDivisibleMP(Amount); } else { amountStr = FormatIndivisibleMP(Amount); } + txobj.push_back(Pair("amount", amountStr)); + break; + case 21: //metadex sell + txobj.push_back(Pair("type", "MetaDEx token trade")); + divisible = isPropertyDivisible(PropertyID); + desiredDivisible = isPropertyDivisible(PropertyID_2); + if (divisible) { amountStr = FormatDivisibleMP(Amount); } else { amountStr = FormatIndivisibleMP(Amount); } + if (desiredDivisible) { amountDStr = FormatDivisibleMP(Amount_2); } else { amountDStr = FormatIndivisibleMP(Amount_2); } + txobj.push_back(Pair("amountoffered", amountStr)); + txobj.push_back(Pair("propertyoffered", (uint64_t)PropertyID)); + txobj.push_back(Pair("propertyofferedisdivisible", divisible)); + txobj.push_back(Pair("amountdesired", amountDStr)); + txobj.push_back(Pair("propertydesired", (uint64_t)PropertyID_2)); + txobj.push_back(Pair("propertydesiredisdivisible", desiredDivisible)); + txobj.push_back(Pair("action", additional)); + break; + } + string txDesc = write_string(Value(txobj), false); + (void) pendingAdd(txid, FromAddress, prop, amount, TransactionType, txDesc); } return txid; diff --git a/src/mastercore.h b/src/mastercore.h index 0517ce2f68775..6cd29807b9e8b 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -427,11 +427,14 @@ class CMPPending string src; // the FromAddress unsigned int prop; int64_t amount; + int64_t type; + string desc; // the description void print(uint256 txid) const { - printf("%s : %s %d %ld\n", txid.GetHex().c_str(), src.c_str(), prop, amount); + printf("%s : %s %d %ld %ld %s\n", txid.GetHex().c_str(), src.c_str(), prop, amount, type, desc.c_str()); } + }; //temp - only supporting 100,000 properties per eco here, research best way to expand array @@ -464,7 +467,7 @@ extern CMPTxList *p_txlistdb; extern CMPTradeList *t_tradelistdb; typedef std::map PendingMap; - +extern PendingMap my_pending; string strMPProperty(unsigned int i); int GetHeight(void); diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 87262ce92a04d..c24248ae3abe5 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -126,6 +126,77 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : void TXHistoryDialog::UpdateHistory() { + int rowcount = 0; + + // handle pending transactions first + for(PendingMap::iterator it = my_pending.begin(); it != my_pending.end(); ++it) + { + CMPPending *p_pending = &(it->second); + //p_pending->print(txid); + + string senderAddress = p_pending->src; + uint64_t propertyId = p_pending->prop; + bool divisible = isPropertyDivisible(propertyId); + string displayAmount; + int64_t amount = p_pending->amount; + string displayToken; + string displayValid; + string displayAddress = senderAddress; + int64_t type = p_pending->type; + + if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } + // clean up trailing zeros - good for RPC not so much for UI + displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos ); + if (displayAmount.length() > 0) { std::string::iterator it = displayAmount.end() - 1; if (*it == '.') { displayAmount.erase(it); } } //get rid of trailing dot if non decimal + + if (propertyId < 3) + { + if(propertyId == 1) { displayToken = " MSC"; } + if(propertyId == 2) { displayToken = " TMSC"; } + } + else + { + string s = to_string(propertyId); + displayToken = " SPT#" + s; + } + QString txTimeStr = "Unconfirmed"; + string displayType; + if (type == 0) displayType = "Send"; + if (type == 21) displayType = "MetaDEx Trade"; + displayAmount = "-" + displayAmount; //all pending are outbound + //icon + QIcon ic = QIcon(":/icons/transaction_unconfirmed"); + // add to history + ui->txHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); + QTableWidgetItem *typeCell = new QTableWidgetItem(QString::fromStdString(displayType)); + QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); + QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString("test")); //hash.GetHex())); + iconCell->setIcon(ic); + addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); + addressCell->setForeground(QColor("#707070")); + amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountCell->setForeground(QColor("#EE0000")); + if (rowcount % 2) + { + amountCell->setBackground(QColor("#F0F0F0")); + addressCell->setBackground(QColor("#F0F0F0")); + dateCell->setBackground(QColor("#F0F0F0")); + typeCell->setBackground(QColor("#F0F0F0")); + txidCell->setBackground(QColor("#F0F0F0")); + } + ui->txHistoryTable->setItem(rowcount, 0, iconCell); + ui->txHistoryTable->setItem(rowcount, 1, dateCell); + ui->txHistoryTable->setItem(rowcount, 2, typeCell); + ui->txHistoryTable->setItem(rowcount, 3, addressCell); + ui->txHistoryTable->setItem(rowcount, 4, amountCell); + ui->txHistoryTable->setItem(rowcount, 5, txidCell); + rowcount += 1; + } + + // wallet transactions CWallet *wallet = pwalletMain; string sAddress = ""; string addressParam = ""; @@ -142,7 +213,6 @@ void TXHistoryDialog::UpdateHistory() CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); // iterate backwards - int rowcount = 0; for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; @@ -333,10 +403,28 @@ void TXHistoryDialog::showDetails() Object txobj; uint256 txid; txid.SetHex(ui->txHistoryTable->item(ui->txHistoryTable->currentRow(),5)->text().toStdString()); - int pop = populateRPCTransactionObject(txid, &txobj, ""); - if (0<=pop) + std::string strTXText; + + // first of all check if the TX is a pending tx, if so grab details from pending map + PendingMap::iterator it = my_pending.find(txid); + if (it != my_pending.end()) + { + CMPPending *p_pending = &(it->second); + p_pending->print(txid); + strTXText = p_pending->desc; + } + else + { + // grab details usual way + int pop = populateRPCTransactionObject(txid, &txobj, ""); + if (0<=pop) + { + strTXText = write_string(Value(txobj), false) + "\n"; + } + } + + if (!strTXText.empty()) { - std::string strTXText = write_string(Value(txobj), false) + "\n"; // clean up string from = ","; string to = ",\n "; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 065565f0a5f6e..2fdafe4510ebd 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -208,6 +208,7 @@ void WalletView::setWalletModel(WalletModel *walletModel) sendMPTab->setModel(walletModel); balancesView->setModel(walletModel); metaDExTab->setModel(walletModel); + mpTXTab->setModel(walletModel); if (walletModel) { diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 1973e1fe6c88e..7ee4a831e50f5 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -20,6 +20,7 @@ class LookupAddressDialog; class MetaDExDialog; class SendCoinsRecipient; class TransactionView; +class TXHistoryDialog; class BalancesView; class WalletModel; @@ -80,7 +81,7 @@ class WalletView : public QStackedWidget MetaDExDialog *metaDExTab; TransactionView *transactionView; BalancesView *balancesView; - QWidget *mpTXTab; + TXHistoryDialog *mpTXTab; QWidget *bitcoinTXTab; QProgressDialog *progressDialog; From d74236a2b6b8f9cba5f86934024fa15c6c5dbcbf Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 20:15:33 -0800 Subject: [PATCH 068/141] Some corrections to pending txs in history --- src/mastercore.cpp | 31 ++++++++++++++++++------------- src/qt/txhistorydialog.cpp | 21 +++++++++++---------- src/qt/txhistorydialog.h | 2 +- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 2f64d1f1db9fc..a4eb6806eed23 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -2935,6 +2935,11 @@ const unsigned int prop = PropertyID; return 0; } + int64_t rawTransactionType = TransactionType; + int64_t rawPropertyID = PropertyID; + int64_t rawPropertyID_2 = PropertyID_2; + int64_t rawAmount = Amount; + int64_t rawAmount_2 = Amount_2; vector data; swapByteOrder32(TransactionType); swapByteOrder32(PropertyID); @@ -2970,42 +2975,42 @@ const unsigned int prop = PropertyID; Object txobj; txobj.push_back(Pair("txid", txid.GetHex())); txobj.push_back(Pair("sendingaddress", FromAddress)); - if (TransactionType == MSC_TYPE_SIMPLE_SEND) txobj.push_back(Pair("referenceaddress", ToAddress)); + if (rawTransactionType == MSC_TYPE_SIMPLE_SEND) txobj.push_back(Pair("referenceaddress", ToAddress)); txobj.push_back(Pair("confirmations", 0)); // txobj->push_back(Pair("fee", ValueFromAmount(nFee))); txobj.push_back(Pair("version", (int64_t)0)); //we only send v0 currently so all pending v0 - txobj.push_back(Pair("type_int", (int64_t)TransactionType)); + txobj.push_back(Pair("type_int", (int64_t)rawTransactionType)); bool divisible = false; bool desiredDivisible = false; string amountStr; string amountDStr; - switch (TransactionType) + switch (rawTransactionType) { case 0: //simple send txobj.push_back(Pair("type", "Simple send")); - txobj.push_back(Pair("propertyid", (uint64_t)PropertyID)); - divisible = isPropertyDivisible(PropertyID); + txobj.push_back(Pair("propertyid", rawPropertyID)); + divisible = isPropertyDivisible(rawPropertyID); txobj.push_back(Pair("divisible", divisible)); - if (divisible) { amountStr = FormatDivisibleMP(Amount); } else { amountStr = FormatIndivisibleMP(Amount); } + if (divisible) { amountStr = FormatDivisibleMP(rawAmount); } else { amountStr = FormatIndivisibleMP(rawAmount); } txobj.push_back(Pair("amount", amountStr)); break; case 21: //metadex sell txobj.push_back(Pair("type", "MetaDEx token trade")); - divisible = isPropertyDivisible(PropertyID); - desiredDivisible = isPropertyDivisible(PropertyID_2); - if (divisible) { amountStr = FormatDivisibleMP(Amount); } else { amountStr = FormatIndivisibleMP(Amount); } - if (desiredDivisible) { amountDStr = FormatDivisibleMP(Amount_2); } else { amountDStr = FormatIndivisibleMP(Amount_2); } + divisible = isPropertyDivisible(rawPropertyID); + desiredDivisible = isPropertyDivisible(rawPropertyID_2); + if (divisible) { amountStr = FormatDivisibleMP(rawAmount); } else { amountStr = FormatIndivisibleMP(rawAmount); } + if (desiredDivisible) { amountDStr = FormatDivisibleMP(rawAmount_2); } else { amountDStr = FormatIndivisibleMP(rawAmount_2); } txobj.push_back(Pair("amountoffered", amountStr)); - txobj.push_back(Pair("propertyoffered", (uint64_t)PropertyID)); + txobj.push_back(Pair("propertyoffered", rawPropertyID)); txobj.push_back(Pair("propertyofferedisdivisible", divisible)); txobj.push_back(Pair("amountdesired", amountDStr)); - txobj.push_back(Pair("propertydesired", (uint64_t)PropertyID_2)); + txobj.push_back(Pair("propertydesired", rawPropertyID_2)); txobj.push_back(Pair("propertydesiredisdivisible", desiredDivisible)); txobj.push_back(Pair("action", additional)); break; } string txDesc = write_string(Value(txobj), false); - (void) pendingAdd(txid, FromAddress, prop, amount, TransactionType, txDesc); + (void) pendingAdd(txid, FromAddress, prop, amount, rawTransactionType, txDesc); } return txid; diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index c24248ae3abe5..e5d65d80b848f 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -132,6 +132,8 @@ void TXHistoryDialog::UpdateHistory() for(PendingMap::iterator it = my_pending.begin(); it != my_pending.end(); ++it) { CMPPending *p_pending = &(it->second); + uint256 txid = it->first; + string txidStr = txid.GetHex(); //p_pending->print(txid); string senderAddress = p_pending->src; @@ -165,7 +167,7 @@ void TXHistoryDialog::UpdateHistory() if (type == 21) displayType = "MetaDEx Trade"; displayAmount = "-" + displayAmount; //all pending are outbound //icon - QIcon ic = QIcon(":/icons/transaction_unconfirmed"); + QIcon ic = QIcon(":/icons/transaction_0"); // add to history ui->txHistoryTable->setRowCount(rowcount+1); QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); @@ -173,7 +175,7 @@ void TXHistoryDialog::UpdateHistory() QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString("test")); //hash.GetHex())); + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(txidStr)); //hash.GetHex())); iconCell->setIcon(ic); addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); addressCell->setForeground(QColor("#707070")); @@ -323,11 +325,11 @@ void TXHistoryDialog::UpdateHistory() int confirmations = 1 + GetHeight() - pBlockIndex->nHeight; switch(confirmations) { - case 1: ic = QIcon(":/icons/transaction_1"); - case 2: ic = QIcon(":/icons/transaction_2"); - case 3: ic = QIcon(":/icons/transaction_3"); - case 4: ic = QIcon(":/icons/transaction_4"); - case 5: ic = QIcon(":/icons/transaction_5"); + case 1: ic = QIcon(":/icons/transaction_1"); break; + case 2: ic = QIcon(":/icons/transaction_2"); break; + case 3: ic = QIcon(":/icons/transaction_3"); break; + case 4: ic = QIcon(":/icons/transaction_4"); break; + case 5: ic = QIcon(":/icons/transaction_5"); break; } if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); if (!valid) ic = QIcon(":/icons/transaction_invalid"); @@ -371,7 +373,7 @@ void TXHistoryDialog::UpdateHistory() void TXHistoryDialog::setModel(WalletModel *model) { this->model = model; - //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(UpdateHistory())); } void TXHistoryDialog::contextualMenu(const QPoint &point) @@ -410,8 +412,7 @@ void TXHistoryDialog::showDetails() if (it != my_pending.end()) { CMPPending *p_pending = &(it->second); - p_pending->print(txid); - strTXText = p_pending->desc; + strTXText = "*** THIS TRANSACTION IS UNCONFIRMED ***\n" + p_pending->desc; } else { diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index 1e87c79a3bc23..53db18e05c35d 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -33,7 +33,6 @@ class TXHistoryDialog : public QDialog //void FullRefresh(); explicit TXHistoryDialog(QWidget *parent = 0); void setModel(WalletModel *model); - void UpdateHistory(); void accept(); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ @@ -64,6 +63,7 @@ private slots: void copyAddress(); void copyAmount(); void copyTxID(); + void UpdateHistory(); signals: void doubleClicked(const QModelIndex&); From 3375e0fe9e6d46aea513cbbdc4dc53fa78e483f3 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 30 Nov 2014 20:31:33 -0800 Subject: [PATCH 069/141] Update on block changes and disable update timer --- src/qt/walletmodel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 832091c80c450..d9477a9f27447 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -43,10 +43,11 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p pollTimer->start(MODEL_UPDATE_DELAY); // The above timer is too fast for MasterCore usage, we'll have a new one here + /* updateTimer = new QTimer(this); connect(updateTimer, SIGNAL(timeout()), this, SLOT(forceUpdateBalances())); updateTimer->start(MASTERCORE_UPDATE_DELAY); - + */ subscribeToCoreSignals(); } @@ -151,6 +152,7 @@ void WalletModel::pollBalanceChanged() cachedNumBlocks = chainActive.Height(); checkBalanceChanged(); + forceUpdateBalances(); if(transactionTableModel) transactionTableModel->updateConfirmations(); } From f2e33ff61b632968a5c31edb999b83fc54bf8742 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 14:47:47 -0800 Subject: [PATCH 070/141] Add FormatDivisibleShortMP for UI usage --- src/mastercore.cpp | 12 ++++++++++++ src/mastercore.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index a4eb6806eed23..6470e516efc74 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -320,6 +320,18 @@ bool isNonMainNet() return (TestNet() || RegTest()); } +string FormatDivisibleShortMP(int64_t n) +{ +int64_t n_abs = (n > 0 ? n : -n); +int64_t quotient = n_abs/COIN; +int64_t remainder = n_abs%COIN; +string str = strprintf("%d.%08d", quotient, remainder); +// clean up trailing zeros - good for RPC not so much for UI +str.erase ( str.find_last_not_of('0') + 1, std::string::npos ); +if (str.length() > 0) { std::string::iterator it = str.end() - 1; if (*it == '.') { str.erase(it); } } //get rid of trailing dot if non decimal +return str; +} + // mostly taken from Bitcoin's FormatMoney() string FormatDivisibleMP(int64_t n, bool fSign) { diff --git a/src/mastercore.h b/src/mastercore.h index 6cd29807b9e8b..b44dc0e082ed9 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -178,6 +178,7 @@ TINYFORMAT_FOREACH_ARGNUM(MP_MAKE_ERROR_AND_LOG_FUNC) // forward declarations std::string FormatDivisibleMP(int64_t n, bool fSign = false); +std::string FormatDivisibleShortMP(int64_t); std::string FormatMP(unsigned int, int64_t n, bool fSign = false); uint256 send_MP(const string &FromAddress, const string &ToAddress, const string &RedeemAddress, unsigned int PropertyID, uint64_t Amount); int64_t feeCheck(const string &address); From 23e9cb9830086acd4a05264194869a620f827afe Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 14:48:02 -0800 Subject: [PATCH 071/141] Move order history away from custom list delegate to standard UI elements --- src/qt/forms/orderhistorydialog.ui | 2 +- src/qt/orderhistorydialog.cpp | 76 ++++++++++++++++++++++++++---- src/qt/orderhistorydialog.h | 13 +++++ src/qt/txhistorydialog.cpp | 7 ++- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/qt/forms/orderhistorydialog.ui b/src/qt/forms/orderhistorydialog.ui index 9997070a670dc..9724274c1f1cb 100644 --- a/src/qt/forms/orderhistorydialog.ui +++ b/src/qt/forms/orderhistorydialog.ui @@ -20,7 +20,7 @@ 0 - + diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index fd2279ca17ee1..6ca4b317ab3a3 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -61,8 +61,6 @@ using namespace leveldb; #include #include -#include "orderlistdelegate.h" - OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : QDialog(parent), ui(new Ui::orderHistoryDialog), @@ -70,7 +68,28 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : { ui->setupUi(this); this->model = model; - ui->orderHistoryLW->setItemDelegate(new ListDelegate(ui->orderHistoryLW)); + + // setup + ui->orderHistoryTable->setColumnCount(7); + ui->orderHistoryTable->setHorizontalHeaderItem(0, new QTableWidgetItem(" ")); + ui->orderHistoryTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Date")); + ui->orderHistoryTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Status")); + ui->orderHistoryTable->setHorizontalHeaderItem(3, new QTableWidgetItem("Trade Details")); + ui->orderHistoryTable->setHorizontalHeaderItem(4, new QTableWidgetItem("Sold")); + ui->orderHistoryTable->setHorizontalHeaderItem(5, new QTableWidgetItem("Received")); + ui->orderHistoryTable->verticalHeader()->setVisible(false); +// ui->txHistoryTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); +// ui->txHistoryTable->setShowGrid(false); + ui->orderHistoryTable->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->orderHistoryTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->orderHistoryTable->setSelectionMode(QAbstractItemView::SingleSelection); + ui->orderHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); + ui->orderHistoryTable->setColumnWidth(0, 23); + ui->orderHistoryTable->setColumnWidth(1, 150); + ui->orderHistoryTable->setColumnWidth(2, 130); + ui->orderHistoryTable->setColumnWidth(4, 200); + ui->orderHistoryTable->setColumnWidth(5, 200); + ui->orderHistoryTable->setColumnWidth(6, 0); CWallet *wallet = pwalletMain; string sAddress = ""; @@ -84,6 +103,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : int64_t nEndBlock = 999999; Array response; //prep an array to hold our output + int rowcount = 0; // rewrite to use original listtransactions methodology from core LOCK(wallet->cs_wallet); @@ -202,15 +222,13 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : if((orderOpen) && (partialFilled)) statusText = "PART FILLED"; // add to list - QListWidgetItem *qItem = new QListWidgetItem(); - qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); string displayText = "Sell "; string displayIn = "+"; string displayOut = "-"; string displayInToken; string displayOutToken; - if(divisibleForSale) { displayText += FormatDivisibleMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } + if(divisibleForSale) { displayText += FormatDivisibleShortMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } if(propertyIdForSale < 3) { if(propertyIdForSale == 1) { displayText += " MSC for "; displayOutToken = " MSC"; } @@ -222,7 +240,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : displayText += " SPT#" + s + " for "; displayOutToken = " SPT#" + s; } - if(divisibleDesired) { displayText += FormatDivisibleMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } + if(divisibleDesired) { displayText += FormatDivisibleShortMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } if(propertyIdDesired < 3) { if(propertyIdDesired == 1) { displayText += " MSC"; displayInToken = " MSC"; } @@ -234,8 +252,8 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : displayText += " SPT#" + s; displayInToken = " SPT#" + s; } - if(divisibleDesired) { displayIn += FormatDivisibleMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } - if(divisibleForSale) { displayOut += FormatDivisibleMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } + if(divisibleDesired) { displayIn += FormatDivisibleShortMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } + if(divisibleForSale) { displayOut += FormatDivisibleShortMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } if(totalBought == 0) displayIn = "0"; if(totalSold == 0) displayOut = "0"; displayIn += displayInToken; @@ -243,6 +261,45 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : QDateTime txTime; txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + + //icon + QIcon ic = QIcon(":/icons/transaction_0"); + // add to order history + ui->orderHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); + QTableWidgetItem *statusCell = new QTableWidgetItem(QString::fromStdString(statusText)); + QTableWidgetItem *infoCell = new QTableWidgetItem(QString::fromStdString(displayText)); + QTableWidgetItem *amountOutCell = new QTableWidgetItem(QString::fromStdString(displayOut)); + QTableWidgetItem *amountInCell = new QTableWidgetItem(QString::fromStdString(displayIn)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); + iconCell->setIcon(ic); + //addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); + //addressCell->setForeground(QColor("#707070")); + amountOutCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountOutCell->setForeground(QColor("#EE0000")); + amountInCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountInCell->setForeground(QColor("#00AA00")); + if (rowcount % 2) + { + dateCell->setBackground(QColor("#F0F0F0")); + statusCell->setBackground(QColor("#F0F0F0")); + infoCell->setBackground(QColor("#F0F0F0")); + amountOutCell->setBackground(QColor("#F0F0F0")); + amountInCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); + txidCell->setBackground(QColor("#F0F0F0")); + } + ui->orderHistoryTable->setItem(rowcount, 0, iconCell); + ui->orderHistoryTable->setItem(rowcount, 1, dateCell); + ui->orderHistoryTable->setItem(rowcount, 2, statusCell); + ui->orderHistoryTable->setItem(rowcount, 3, infoCell); + ui->orderHistoryTable->setItem(rowcount, 4, amountOutCell); + ui->orderHistoryTable->setItem(rowcount, 5, amountInCell); + ui->orderHistoryTable->setItem(rowcount, 6, txidCell); + rowcount += 1; + +/* qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); @@ -250,6 +307,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); qItem->setData(Qt::UserRole + 6, txTimeStr); ui->orderHistoryLW->addItem(qItem); +*/ } } } diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h index ea858b5971b8a..226c07b25cf69 100644 --- a/src/qt/orderhistorydialog.h +++ b/src/qt/orderhistorydialog.h @@ -9,6 +9,7 @@ #include #include +#include class OptionsModel; @@ -33,6 +34,18 @@ class OrderHistoryDialog : public QDialog /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ QWidget *setupTabChain(QWidget *prev); + // QDialog *txDlg; + QTableWidgetItem *iconCell; + QTableWidgetItem *dateCell; + QTableWidgetItem *statusCell; + QTableWidgetItem *Cell; + QTableWidgetItem *amountOutCell; + QTableWidgetItem *amountInCell; + QTableWidgetItem *txidCell; + QLayout *dlgLayout; +// QTextEdit *dlgTextEdit; +// QDialogButtonBox *buttonBox; + QPushButton *closeButton; public slots: diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index e5d65d80b848f..2ef57548508f4 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -188,6 +188,7 @@ void TXHistoryDialog::UpdateHistory() dateCell->setBackground(QColor("#F0F0F0")); typeCell->setBackground(QColor("#F0F0F0")); txidCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); } ui->txHistoryTable->setItem(rowcount, 0, iconCell); ui->txHistoryTable->setItem(rowcount, 1, dateCell); @@ -298,10 +299,7 @@ void TXHistoryDialog::UpdateHistory() string displayValid; string displayAddress; if (IsMyAddress(senderAddress)) { displayAddress = senderAddress; } else { displayAddress = refAddress; } - if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } - // clean up trailing zeros - good for RPC not so much for UI - displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos ); - if (displayAmount.length() > 0) { std::string::iterator it = displayAmount.end() - 1; if (*it == '.') { displayAmount.erase(it); } } //get rid of trailing dot if non decimal + if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; } if (propertyId < 3) { @@ -355,6 +353,7 @@ void TXHistoryDialog::UpdateHistory() dateCell->setBackground(QColor("#F0F0F0")); typeCell->setBackground(QColor("#F0F0F0")); txidCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); } ui->txHistoryTable->setItem(rowcount, 0, iconCell); ui->txHistoryTable->setItem(rowcount, 1, dateCell); From 09391d6e9f197e337cb5642442e8cbab092237a8 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 14:59:08 -0800 Subject: [PATCH 072/141] Remove delegate stuff --- src/qt/Makefile.am | 3 - src/qt/orderhistorydialog.cpp | 14 ++++- src/qt/orderlistdelegate.cpp | 106 ---------------------------------- src/qt/orderlistdelegate.h | 14 ----- 4 files changed, 11 insertions(+), 126 deletions(-) delete mode 100644 src/qt/orderlistdelegate.cpp delete mode 100644 src/qt/orderlistdelegate.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 82a7361938592..e82908d9c3e8e 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -146,7 +146,6 @@ QT_MOC_CPP = \ moc_metadexdialog.cpp \ moc_orderhistorydialog.cpp \ moc_txhistorydialog.cpp \ - moc_orderlistdelegate.cpp \ moc_lookupspdialog.cpp \ moc_lookupaddressdialog.cpp \ moc_lookuptxdialog.cpp \ @@ -222,7 +221,6 @@ BITCOIN_QT_H = \ lookupspdialog.h \ lookupaddressdialog.h \ lookuptxdialog.h \ - orderlistdelegate.h \ signverifymessagedialog.h \ splashscreen.h \ trafficgraphwidget.h \ @@ -343,7 +341,6 @@ BITCOIN_QT_CPP += \ metadexdialog.cpp \ orderhistorydialog.cpp \ txhistorydialog.cpp \ - orderlistdelegate.cpp \ lookupspdialog.cpp \ lookupaddressdialog.cpp \ lookuptxdialog.cpp \ diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 6ca4b317ab3a3..c343e5fee5400 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -86,9 +86,9 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); ui->orderHistoryTable->setColumnWidth(0, 23); ui->orderHistoryTable->setColumnWidth(1, 150); - ui->orderHistoryTable->setColumnWidth(2, 130); - ui->orderHistoryTable->setColumnWidth(4, 200); - ui->orderHistoryTable->setColumnWidth(5, 200); + ui->orderHistoryTable->setColumnWidth(2, 110); + ui->orderHistoryTable->setColumnWidth(4, 180); + ui->orderHistoryTable->setColumnWidth(5, 180); ui->orderHistoryTable->setColumnWidth(6, 0); CWallet *wallet = pwalletMain; @@ -290,6 +290,14 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : iconCell->setBackground(QColor("#F0F0F0")); txidCell->setBackground(QColor("#F0F0F0")); } + if((!orderOpen) && (filled)) //make filled orders background + { + dateCell->setForeground(QColor("#707070")); + statusCell->setForeground(QColor("#707070")); + infoCell->setForeground(QColor("#707070")); + amountOutCell->setForeground(QColor("#993333")); + amountInCell->setForeground(QColor("#33CC66")); + } ui->orderHistoryTable->setItem(rowcount, 0, iconCell); ui->orderHistoryTable->setItem(rowcount, 1, dateCell); ui->orderHistoryTable->setItem(rowcount, 2, statusCell); diff --git a/src/qt/orderlistdelegate.cpp b/src/qt/orderlistdelegate.cpp deleted file mode 100644 index 459af6ed56668..0000000000000 --- a/src/qt/orderlistdelegate.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "orderlistdelegate.h" - -ListDelegate::ListDelegate(QObject *parent) -{ - -} - -void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const -{ - QRect r = option.rect; - QPen linePen(QColor::fromRgb(211,211,211), 1, Qt::SolidLine); - QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine); - painter->setPen(linePen); - - // alt the colors - painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) ); - painter->drawRect(r); - // draw border - painter->setPen(linePen); - painter->drawLine(r.topLeft(),r.topRight()); - painter->drawLine(r.topRight(),r.bottomRight()); - painter->drawLine(r.bottomLeft(),r.bottomRight()); - painter->drawLine(r.topLeft(),r.bottomLeft()); - painter->setPen(fontPen); - - // prepare the data for the entry -// QIcon ic = QIcon(qvariant_cast(index.data(Qt::DecorationRole))); -// string shortTXID = QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,12)); - QString txidsender = "ADDR: " + QString::fromStdString(index.data(Qt::UserRole + 5).toString().toStdString().substr(0,18)) + "..."; - txidsender += " TX: " + QString::fromStdString(index.data(Qt::DisplayRole).toString().toStdString().substr(0,18)) + "..."; -// txidstatus += "....\tSTATUS: " + index.data(Qt::UserRole + 4).toString(); - QString displayText = index.data(Qt::UserRole + 1).toString(); - QString amountBought = index.data(Qt::UserRole + 2).toString(); - QString amountSold = index.data(Qt::UserRole + 3).toString(); - QString status = index.data(Qt::UserRole + 4).toString(); - QString senderText = index.data(Qt::UserRole + 5).toString(); - QString txTimeText = index.data(Qt::UserRole + 6).toString(); - - // add the appropriate status icon - int imageSpace = 10; - QIcon ic = QIcon(":/icons/meta_cancelled"); - if(status == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); - if(status == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); - if(status == "FILLED") ic = QIcon(":/icons/meta_filled"); - if(status == "OPEN") ic = QIcon(":/icons/meta_open"); - if(status == "PART FILLED") ic = QIcon(":/icons/meta_partial"); - if (!ic.isNull()) - { - r = option.rect.adjusted(5, 10, -10, -10); - ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft); - imageSpace = 60; - } - - // setup pens - QPen penBlack(QColor("#000000")); - QPen penRed(QColor("#CC0000")); - QPen penGreen(QColor("#00AA00")); - QPen penGrey(QColor("#606060")); - - QFont font = painter->font(); - painter->setPen(penBlack); - // add the status - font.setItalic(false); - painter->setFont(font); - r = option.rect.adjusted(imageSpace-19, 0, -10, -25); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, status, &r); - // add the datetime - painter->setPen(penGrey); - font.setItalic(true); - painter->setFont(font); - r = option.rect.adjusted(imageSpace-19, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txTimeText, &r); - // add the displaytext - painter->setPen(penBlack); - r = option.rect.adjusted(imageSpace+115, 0, -10, -25); - font.setBold(true); - font.setItalic(false); - painter->setFont(font); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, displayText, &r); - // add the txid/sender - painter->setPen(penGrey); - font.setBold(false); - painter->setFont(font); - r = option.rect.adjusted(imageSpace+115, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, txidsender, &r); - font.setBold(true); - painter->setFont(font); - if("0 " != amountBought.toStdString().substr(0,2)) painter->setPen(penGreen); - r = option.rect.adjusted(imageSpace+115, 0, -10, -25); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignRight, amountBought, &r); - if("0 " != amountSold.toStdString().substr(0,2)) painter->setPen(penRed); - r = option.rect.adjusted(imageSpace+115, 25, -10, 0); - painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignRight, amountSold, &r); - font.setBold(false); - painter->setFont(font); - -} - -QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const -{ - return QSize(200, 50); // very dumb value? -} - -ListDelegate::~ListDelegate() -{ -} diff --git a/src/qt/orderlistdelegate.h b/src/qt/orderlistdelegate.h deleted file mode 100644 index c1912d979825f..0000000000000 --- a/src/qt/orderlistdelegate.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -class ListDelegate : public QAbstractItemDelegate -{ - public: - ListDelegate(QObject *parent = 0); - - void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; - QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; - - virtual ~ListDelegate(); - -}; From 47bac90436bc753f8ea6bd3a18d89aa8ad23d60e Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 15:31:16 -0800 Subject: [PATCH 073/141] Fix icons and decolor unmatched trades --- src/qt/orderhistorydialog.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index c343e5fee5400..c46e38d2bf68a 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -264,6 +264,12 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : //icon QIcon ic = QIcon(":/icons/transaction_0"); + if(statusText == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); + if(statusText == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); + if(statusText == "FILLED") ic = QIcon(":/icons/meta_filled"); + if(statusText == "OPEN") ic = QIcon(":/icons/meta_open"); + if(statusText == "PART FILLED") ic = QIcon(":/icons/meta_partial"); + // add to order history ui->orderHistoryTable->setRowCount(rowcount+1); QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); @@ -296,8 +302,11 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : statusCell->setForeground(QColor("#707070")); infoCell->setForeground(QColor("#707070")); amountOutCell->setForeground(QColor("#993333")); - amountInCell->setForeground(QColor("#33CC66")); + amountInCell->setForeground(QColor("#006600")); } + if(displayIn.substr(0,2) == "0 ") amountInCell->setForeground(QColor("#000000")); + if(displayOut.substr(0,2) == "0 ") amountOutCell->setForeground(QColor("#000000")); + ui->orderHistoryTable->setItem(rowcount, 0, iconCell); ui->orderHistoryTable->setItem(rowcount, 1, dateCell); ui->orderHistoryTable->setItem(rowcount, 2, statusCell); From b816c658c1837c65d004133718095407bdc9a9b3 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 17:00:17 -0800 Subject: [PATCH 074/141] Initial UI support for MetaDEx cancels --- src/qt/Makefile.am | 4 + src/qt/forms/metadexcanceldialog.ui | 223 ++++++++++++++++++++++++++++ src/qt/metadexcanceldialog.cpp | 176 ++++++++++++++++++++++ src/qt/metadexcanceldialog.h | 54 +++++++ src/qt/walletview.cpp | 3 + src/qt/walletview.h | 2 + 6 files changed, 462 insertions(+) create mode 100644 src/qt/forms/metadexcanceldialog.ui create mode 100644 src/qt/metadexcanceldialog.cpp create mode 100644 src/qt/metadexcanceldialog.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index e82908d9c3e8e..5134dc6f3cdcd 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -103,6 +103,7 @@ QT_FORMS_UI = \ forms/sendmpdialog.ui \ forms/orderhistorydialog.ui \ forms/txhistorydialog.ui \ + forms/metadexcanceldialog.ui \ forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/lookupaddressdialog.ui \ @@ -144,6 +145,7 @@ QT_MOC_CPP = \ moc_sendcoinsentry.cpp \ moc_sendmpdialog.cpp \ moc_metadexdialog.cpp \ + moc_metadexcanceldialog.cpp \ moc_orderhistorydialog.cpp \ moc_txhistorydialog.cpp \ moc_lookupspdialog.cpp \ @@ -216,6 +218,7 @@ BITCOIN_QT_H = \ sendcoinsentry.h \ sendmpdialog.h \ metadexdialog.h \ + metadexcanceldialog.h \ orderhistorydialog.h \ txhistorydialog.h \ lookupspdialog.h \ @@ -338,6 +341,7 @@ BITCOIN_QT_CPP += \ sendcoinsdialog.cpp \ sendcoinsentry.cpp \ sendmpdialog.cpp \ + metadexcanceldialog.cpp \ metadexdialog.cpp \ orderhistorydialog.cpp \ txhistorydialog.cpp \ diff --git a/src/qt/forms/metadexcanceldialog.ui b/src/qt/forms/metadexcanceldialog.ui new file mode 100644 index 0000000000000..534ec95933730 --- /dev/null +++ b/src/qt/forms/metadexcanceldialog.ui @@ -0,0 +1,223 @@ + + + MetaDExCancelDialog + + + + 0 + 0 + 664 + 474 + + + + Form + + + + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + + + 75 + true + + + + padding-bottom:4px; + + + Cancellation Type: + + + + + + + padding-left:10px; + + + Cancel by pair + + + + + + + padding-left:10px; + + + Cancel by price + + + + + + + padding-left:10px; + + + Cancel everything + + + + + + + + 75 + true + + + + padding-top:10px;padding-bottom:4px; + + + Cancellation Criteria: + + + + + + + 0 + + + 10 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 8 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 8 + 20 + + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Send Cancel Request + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 8 + 20 + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/src/qt/metadexcanceldialog.cpp b/src/qt/metadexcanceldialog.cpp new file mode 100644 index 0000000000000..dea45e51e8cc9 --- /dev/null +++ b/src/qt/metadexcanceldialog.cpp @@ -0,0 +1,176 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "metadexcanceldialog.h" +#include "ui_metadexcanceldialog.h" + +#include "addresstablemodel.h" +#include "bitcoinunits.h" +#include "coincontroldialog.h" +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" +#include "base58.h" +#include "coincontrol.h" +#include "ui_interface.h" + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" + +// potentially overzealous includes here +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +// end potentially overzealous includes +using namespace json_spirit; // since now using Array in mastercore.h this needs to come first + +#include "mastercore.h" +using namespace mastercore; + +// potentially overzealous using here +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace leveldb; +// end potentially overzealous using + +#include "mastercore_dex.h" +#include "mastercore_parse_string.h" +#include "mastercore_tx.h" +#include "mastercore_sp.h" + +#include +#include +#include +#include + +MetaDExCancelDialog::MetaDExCancelDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::MetaDExCancelDialog), + model(0) +{ + ui->setupUi(this); + + connect(ui->radioCancelPair, SIGNAL(clicked()),this, SLOT(rdoCancelPair())); + connect(ui->radioCancelPrice, SIGNAL(clicked()),this, SLOT(rdoCancelPrice())); + connect(ui->radioCancelEverything, SIGNAL(clicked()),this, SLOT(rdoCancelEverything())); + +} +void MetaDExCancelDialog::rdoCancelPair() +{ + // calculate which pairs are currently open + ui->cancelCombo->clear(); + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + md_Set & indexes = (it->second); + // loop through each entry and sum up any sells for the right pair + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if(IsMyAddress(obj.getAddr())) + { + string comboStr; + string sellToken; + string desiredToken; + // work out pair name + sellToken = getPropertyName(obj.getProperty()).c_str(); + if(sellToken.size()>30) sellToken=sellToken.substr(0,30)+"..."; + string sellId = static_cast( &(ostringstream() << obj.getProperty()) )->str(); + sellToken += " (#" + sellId + ")"; + desiredToken = getPropertyName(obj.getDesProperty()).c_str(); + if(desiredToken.size()>30) desiredToken=desiredToken.substr(0,30)+"..."; + string desiredId = static_cast( &(ostringstream() << obj.getDesProperty()) )->str(); + desiredToken += " (#" + desiredId + ")"; + comboStr = "Cancel all orders selling " + sellToken + " for " + desiredToken; + //only add if not already there + int index = ui->cancelCombo->findText(QString::fromStdString(comboStr)); + if ( index == -1 ) { ui->cancelCombo->addItem(QString::fromStdString(comboStr),QString::fromStdString(sellId+"/"+desiredId)); } + } + } + } + } +} + +void MetaDExCancelDialog::rdoCancelPrice() +{ + // calculate which pairs are currently open and their prices + ui->cancelCombo->clear(); + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + XDOUBLE price = (1/it->first); + string priceStr = price.str(15, std::ios_base::fixed); + md_Set & indexes = (it->second); + // loop through each entry and sum up any sells for the right pair + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if(IsMyAddress(obj.getAddr())) + { + string comboStr; + string sellToken; + string desiredToken; + // work out pair name + sellToken = getPropertyName(obj.getProperty()).c_str(); + if(sellToken.size()>30) sellToken=sellToken.substr(0,30)+"..."; + string sellId = static_cast( &(ostringstream() << obj.getProperty()) )->str(); + sellToken += " (#" + sellId + ")"; + desiredToken = getPropertyName(obj.getDesProperty()).c_str(); + if(desiredToken.size()>30) desiredToken=desiredToken.substr(0,30)+"..."; + string desiredId = static_cast( &(ostringstream() << obj.getDesProperty()) )->str(); + desiredToken += " (#" + desiredId + ")"; + comboStr = "Cancel all orders priced at " + priceStr + " selling " + sellToken + " for " + desiredToken; + //only add if not already there + int index = ui->cancelCombo->findText(QString::fromStdString(comboStr)); + if ( index == -1 ) { ui->cancelCombo->addItem(QString::fromStdString(comboStr),QString::fromStdString(sellId+"/"+desiredId)); } + } + } + } + } + +} + +void MetaDExCancelDialog::rdoCancelEverything() +{ + // only one option here + ui->cancelCombo->clear(); + ui->cancelCombo->addItem("All currently active sell orders","ALL"); //use last possible ID for summary for now +} + +void MetaDExCancelDialog::setModel(WalletModel *model) +{ + this->model = model; +// connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); +} + +void MetaDExCancelDialog::sendCancelTransaction() +{ + +} + diff --git a/src/qt/metadexcanceldialog.h b/src/qt/metadexcanceldialog.h new file mode 100644 index 0000000000000..5a29229e951b8 --- /dev/null +++ b/src/qt/metadexcanceldialog.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef METADEXCANCELDIALOG_H +#define METADEXCANCELDIALOG_H + +#include "walletmodel.h" + +#include +#include + +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace Ui { + class MetaDExCancelDialog; +} + +/** Dialog for sending Master Protocol tokens */ +class MetaDExCancelDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MetaDExCancelDialog(QWidget *parent = 0); + + void setModel(WalletModel *model); + void sendCancelTransaction(); + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + +public slots: + void rdoCancelPair(); + void rdoCancelPrice(); + void rdoCancelEverything(); + +private: + Ui::MetaDExCancelDialog *ui; + WalletModel *model; + +private slots: + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); +}; + +#endif // METADEXCANCELDIALOG_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 2fdafe4510ebd..16f8f9c69882d 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -17,6 +17,7 @@ #include "lookupspdialog.h" #include "lookuptxdialog.h" #include "lookupaddressdialog.h" +#include "metadexcanceldialog.h" #include "metadexdialog.h" #include "signverifymessagedialog.h" #include "transactiontablemodel.h" @@ -109,11 +110,13 @@ WalletView::WalletView(QWidget *parent): exchangePage = new QWidget(this); QVBoxLayout *exvbox = new QVBoxLayout(); metaDExTab = new MetaDExDialog(); + cancelTab = new MetaDExCancelDialog(); QTabWidget *exTabHolder = new QTabWidget(); orderHistoryTab = new OrderHistoryDialog; //exTabHolder->addTab(new QWidget(),tr("Trade Bitcoin/Mastercoin")); not yet implemented exTabHolder->addTab(metaDExTab,tr("Trade Mastercoin/Smart Properties")); exTabHolder->addTab(orderHistoryTab,tr("Order History")); + exTabHolder->addTab(cancelTab,tr("Cancel Orders")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 7ee4a831e50f5..140d57d4bba5a 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -18,6 +18,7 @@ class LookupSPDialog; class LookupTXDialog; class LookupAddressDialog; class MetaDExDialog; +class MetaDExCancelDialog; class SendCoinsRecipient; class TransactionView; class TXHistoryDialog; @@ -79,6 +80,7 @@ class WalletView : public QStackedWidget LookupAddressDialog *addressLookupTab; OrderHistoryDialog *orderHistoryTab; MetaDExDialog *metaDExTab; + MetaDExCancelDialog *cancelTab; TransactionView *transactionView; BalancesView *balancesView; TXHistoryDialog *mpTXTab; From b70c70240bca2d63196013ad5f3609bd352eb238 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 17:43:09 -0800 Subject: [PATCH 075/141] Update history with signal --- src/qt/orderhistorydialog.cpp | 37 ++++++----------------------------- src/qt/orderhistorydialog.h | 2 +- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index c46e38d2bf68a..cd03332682bd5 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -78,8 +78,6 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->setHorizontalHeaderItem(4, new QTableWidgetItem("Sold")); ui->orderHistoryTable->setHorizontalHeaderItem(5, new QTableWidgetItem("Received")); ui->orderHistoryTable->verticalHeader()->setVisible(false); -// ui->txHistoryTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); -// ui->txHistoryTable->setShowGrid(false); ui->orderHistoryTable->setSelectionBehavior(QAbstractItemView::SelectRows); ui->orderHistoryTable->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->orderHistoryTable->setSelectionMode(QAbstractItemView::SingleSelection); @@ -91,6 +89,11 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->setColumnWidth(5, 180); ui->orderHistoryTable->setColumnWidth(6, 0); + Update(); +} + +void OrderHistoryDialog::Update() +{ CWallet *wallet = pwalletMain; string sAddress = ""; string addressParam = ""; @@ -315,44 +318,16 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->setItem(rowcount, 5, amountInCell); ui->orderHistoryTable->setItem(rowcount, 6, txidCell); rowcount += 1; - -/* - qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayText)); - qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayIn)); - qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayOut)); - qItem->setData(Qt::UserRole + 4, QString::fromStdString(statusText)); - qItem->setData(Qt::UserRole + 5, QString::fromStdString(address)); - qItem->setData(Qt::UserRole + 6, txTimeStr); - ui->orderHistoryLW->addItem(qItem); -*/ } } } - // don't burn time doing more work than we need to -// if ((int)response.size() >= (nCount+nFrom)) break; } } - // sort array here and cut on nFrom and nCount -// if (nFrom > (int)response.size()) -// nFrom = response.size(); -// if ((nFrom + nCount) > (int)response.size()) -// nCount = response.size() - nFrom; -// Array::iterator first = response.begin(); -// std::advance(first, nFrom); -// Array::iterator last = response.begin(); -// std::advance(last, nFrom+nCount); - -// if (last != response.end()) response.erase(last, response.end()); -// if (first != response.begin()) response.erase(response.begin(), first); - -// std::reverse(response.begin(), response.end()); // return oldest to newest? - // return response; // return response array for JSON serialization - } void OrderHistoryDialog::setModel(WalletModel *model) { this->model = model; - //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(Update())); } diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h index 226c07b25cf69..7b7fcb3a5880b 100644 --- a/src/qt/orderhistorydialog.h +++ b/src/qt/orderhistorydialog.h @@ -49,7 +49,7 @@ class OrderHistoryDialog : public QDialog public slots: - //void switchButtonClicked(); + void Update(); private: Ui::orderHistoryDialog *ui; From f7a597ab99b3a7e8133f9459a246f3683a1e29a2 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 18:02:10 -0800 Subject: [PATCH 076/141] Right click handler for trade history --- src/qt/orderhistorydialog.cpp | 33 +++++++++++++++++++++++++++++++++ src/qt/orderhistorydialog.h | 5 +++++ 2 files changed, 38 insertions(+) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index cd03332682bd5..ee23cbc2073f3 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -88,6 +88,21 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->setColumnWidth(4, 180); ui->orderHistoryTable->setColumnWidth(5, 180); ui->orderHistoryTable->setColumnWidth(6, 0); + ui->orderHistoryTable->setContextMenuPolicy(Qt::CustomContextMenu); + + // Actions + QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this); + QAction *showDetailsAction = new QAction(tr("Show trade details"), this); + + contextMenu = new QMenu(); + contextMenu->addAction(copyTxIDAction); + contextMenu->addAction(showDetailsAction); + + // Connect actions + connect(ui->orderHistoryTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); + connect(ui->orderHistoryTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails())); + connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID())); + connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); Update(); } @@ -331,3 +346,21 @@ void OrderHistoryDialog::setModel(WalletModel *model) connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(Update())); } +void OrderHistoryDialog::contextualMenu(const QPoint &point) +{ + QModelIndex index = ui->orderHistoryTable->indexAt(point); + if(index.isValid()) + { + contextMenu->exec(QCursor::pos()); + } +} + +void OrderHistoryDialog::copyTxID() +{ + GUIUtil::setClipboard(ui->orderHistoryTable->item(ui->orderHistoryTable->currentRow(),6)->text()); +} + +void OrderHistoryDialog::showDetails() +{ + +} diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h index 7b7fcb3a5880b..eef11c9a5936b 100644 --- a/src/qt/orderhistorydialog.h +++ b/src/qt/orderhistorydialog.h @@ -10,6 +10,7 @@ #include #include #include +#include class OptionsModel; @@ -50,10 +51,14 @@ class OrderHistoryDialog : public QDialog public slots: void Update(); + void contextualMenu(const QPoint &); + void showDetails(); + void copyTxID(); private: Ui::orderHistoryDialog *ui; WalletModel *model; + QMenu *contextMenu; private slots: //void buyRecalc(); From 3501df6927b32b83e38e9f1e9a448b16b9225b77 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 18:38:40 -0800 Subject: [PATCH 077/141] Fix models --- src/qt/orderhistorydialog.cpp | 100 +++++++++++++++++++++++++++++----- src/qt/txhistorydialog.cpp | 5 +- src/qt/walletview.cpp | 2 + 3 files changed, 90 insertions(+), 17 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index ee23cbc2073f3..35fce8a5dece2 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -67,7 +67,6 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : model(0) { ui->setupUi(this); - this->model = model; // setup ui->orderHistoryTable->setColumnCount(7); @@ -109,26 +108,101 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : void OrderHistoryDialog::Update() { + //pending orders + int rowcount = 0; + + // handle pending transactions first + for(PendingMap::iterator it = my_pending.begin(); it != my_pending.end(); ++it) + { + CMPPending *p_pending = &(it->second); + uint256 txid = it->first; + string txidStr = txid.GetHex(); + + string senderAddress = p_pending->src; + uint64_t propertyId = p_pending->prop; + bool divisible = isPropertyDivisible(propertyId); + string displayAmount; + int64_t amount = p_pending->amount; + string displayToken; + string displayValid; + string displayAddress = senderAddress; + int64_t type = p_pending->type; +printf("pending type %ld\n",type); + if (type == 21) + { + if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } + QString txTimeStr = "Unconfirmed"; + string statusText = "Pending"; + string displayText = "Sell "; + string displayInToken; + string displayOutToken; + if(divisible) { displayText += FormatDivisibleShortMP(amount); } else { displayText += FormatIndivisibleMP(amount); } + if(propertyId < 3) + { + if(propertyId == 1) { displayText += " MSC"; displayOutToken = " MSC"; } + if(propertyId == 2) { displayText += " TMSC"; displayOutToken = " TMSC"; } + } + else + { + string s = to_string(propertyId); + displayText += " SPT#" + s + ""; + displayOutToken = " SPT#" + s; + } + string displayIn = "0 " + displayInToken; + string displayOut = "-0 " + displayOutToken; + //icon + QIcon ic = QIcon(":/icons/transaction_0"); + // add to history + ui->orderHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); + QTableWidgetItem *statusCell = new QTableWidgetItem(QString::fromStdString(statusText)); + QTableWidgetItem *infoCell = new QTableWidgetItem(QString::fromStdString(displayText)); + QTableWidgetItem *amountOutCell = new QTableWidgetItem(QString::fromStdString(displayOut)); + QTableWidgetItem *amountInCell = new QTableWidgetItem(QString::fromStdString(displayIn)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(txidStr)); + iconCell->setIcon(ic); + amountOutCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountOutCell->setForeground(QColor("#EE0000")); + amountInCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountInCell->setForeground(QColor("#00AA00")); + if (rowcount % 2) + { + dateCell->setBackground(QColor("#F0F0F0")); + statusCell->setBackground(QColor("#F0F0F0")); + infoCell->setBackground(QColor("#F0F0F0")); + amountOutCell->setBackground(QColor("#F0F0F0")); + amountInCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); + txidCell->setBackground(QColor("#F0F0F0")); + } + amountInCell->setForeground(QColor("#000000")); + amountOutCell->setForeground(QColor("#000000")); + + ui->orderHistoryTable->setItem(rowcount, 0, iconCell); + ui->orderHistoryTable->setItem(rowcount, 1, dateCell); + ui->orderHistoryTable->setItem(rowcount, 2, statusCell); + ui->orderHistoryTable->setItem(rowcount, 3, infoCell); + ui->orderHistoryTable->setItem(rowcount, 4, amountOutCell); + ui->orderHistoryTable->setItem(rowcount, 5, amountInCell); + ui->orderHistoryTable->setItem(rowcount, 6, txidCell); + rowcount += 1; + } + } + + + //wallet orders CWallet *wallet = pwalletMain; string sAddress = ""; - string addressParam = ""; - bool addressFilter; - - addressFilter = false; - int64_t nCount = 10; - int64_t nFrom = 0; int64_t nStartBlock = 0; int64_t nEndBlock = 999999; - Array response; //prep an array to hold our output - int rowcount = 0; - // rewrite to use original listtransactions methodology from core LOCK(wallet->cs_wallet); std::list acentries; CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); - // iterate backwards + // iterate backwards for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; @@ -168,11 +242,11 @@ void OrderHistoryDialog::Update() string address; bool divisibleForSale; bool divisibleDesired; - bool valid; Array tradeArray; uint64_t totalBought = 0; uint64_t totalSold = 0; bool orderOpen = false; + bool valid = false; CMPMetaDEx temp_metadexoffer; CMPTransaction mp_obj; @@ -241,7 +315,7 @@ void OrderHistoryDialog::Update() // add to list string displayText = "Sell "; - string displayIn = "+"; + string displayIn = ""; string displayOut = "-"; string displayInToken; string displayOutToken; diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 2ef57548508f4..c56f9ec414562 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -146,10 +146,7 @@ void TXHistoryDialog::UpdateHistory() string displayAddress = senderAddress; int64_t type = p_pending->type; - if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } - // clean up trailing zeros - good for RPC not so much for UI - displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos ); - if (displayAmount.length() > 0) { std::string::iterator it = displayAmount.end() - 1; if (*it == '.') { displayAmount.erase(it); } } //get rid of trailing dot if non decimal + if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } if (propertyId < 3) { diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 16f8f9c69882d..ebbd170e2bc8f 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -212,6 +212,8 @@ void WalletView::setWalletModel(WalletModel *walletModel) balancesView->setModel(walletModel); metaDExTab->setModel(walletModel); mpTXTab->setModel(walletModel); + cancelTab->setModel(walletModel); + orderHistoryTab->setModel(walletModel); if (walletModel) { From 168830854da71ae3ffc3570a65a8e8bfadd563f5 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 18:43:01 -0800 Subject: [PATCH 078/141] Fix verbage --- src/qt/orderhistorydialog.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 35fce8a5dece2..1f411d4e6b22e 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -83,7 +83,7 @@ OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : ui->orderHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); ui->orderHistoryTable->setColumnWidth(0, 23); ui->orderHistoryTable->setColumnWidth(1, 150); - ui->orderHistoryTable->setColumnWidth(2, 110); + ui->orderHistoryTable->setColumnWidth(2, 100); ui->orderHistoryTable->setColumnWidth(4, 180); ui->orderHistoryTable->setColumnWidth(5, 180); ui->orderHistoryTable->setColumnWidth(6, 0); @@ -127,7 +127,6 @@ void OrderHistoryDialog::Update() string displayValid; string displayAddress = senderAddress; int64_t type = p_pending->type; -printf("pending type %ld\n",type); if (type == 21) { if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } @@ -148,8 +147,9 @@ printf("pending type %ld\n",type); displayText += " SPT#" + s + ""; displayOutToken = " SPT#" + s; } - string displayIn = "0 " + displayInToken; - string displayOut = "-0 " + displayOutToken; + displayText += " (awaiting confirmation)"; + string displayIn = "---"; + string displayOut = "---"; //icon QIcon ic = QIcon(":/icons/transaction_0"); // add to history @@ -306,12 +306,12 @@ printf("pending type %ld\n",type); bool filled = false; if(totalSold>0) partialFilled = true; if(totalSold>=amountForSale) filled = true; - statusText = "UNKNOWN"; - if((!orderOpen) && (!partialFilled)) statusText = "CANCELLED"; - if((!orderOpen) && (partialFilled)) statusText = "PART CANCEL"; - if((!orderOpen) && (filled)) statusText = "FILLED"; - if((orderOpen) && (!partialFilled)) statusText = "OPEN"; - if((orderOpen) && (partialFilled)) statusText = "PART FILLED"; + statusText = "Unknown"; + if((!orderOpen) && (!partialFilled)) statusText = "Cancelled"; + if((!orderOpen) && (partialFilled)) statusText = "Part Cancel"; + if((!orderOpen) && (filled)) statusText = "Filled"; + if((orderOpen) && (!partialFilled)) statusText = "Open"; + if((orderOpen) && (partialFilled)) statusText = "Part Filled"; // add to list string displayText = "Sell "; @@ -356,11 +356,11 @@ printf("pending type %ld\n",type); //icon QIcon ic = QIcon(":/icons/transaction_0"); - if(statusText == "CANCELLED") ic =QIcon(":/icons/meta_cancelled"); - if(statusText == "PART CANCEL") ic = QIcon(":/icons/meta_partialclosed"); - if(statusText == "FILLED") ic = QIcon(":/icons/meta_filled"); - if(statusText == "OPEN") ic = QIcon(":/icons/meta_open"); - if(statusText == "PART FILLED") ic = QIcon(":/icons/meta_partial"); + if(statusText == "Cancelled") ic =QIcon(":/icons/meta_cancelled"); + if(statusText == "Part Cancel") ic = QIcon(":/icons/meta_partialclosed"); + if(statusText == "Filled") ic = QIcon(":/icons/meta_filled"); + if(statusText == "Open") ic = QIcon(":/icons/meta_open"); + if(statusText == "Part Filled") ic = QIcon(":/icons/meta_partial"); // add to order history ui->orderHistoryTable->setRowCount(rowcount+1); From 11ae0162f919be6aad725e128a1c915d7f86a187 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 18:51:04 -0800 Subject: [PATCH 079/141] Order display --- src/qt/orderhistorydialog.cpp | 81 +++++++++++++++++++++++++++++++++++ src/qt/orderhistorydialog.h | 6 ++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index 1f411d4e6b22e..ebd340108747b 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -55,11 +55,13 @@ using namespace leveldb; #include "mastercore_tx.h" #include "mastercore_sp.h" #include "mastercore_parse_string.h" +#include "mastercore_rpc.h" #include #include #include #include +#include OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : QDialog(parent), @@ -436,5 +438,84 @@ void OrderHistoryDialog::copyTxID() void OrderHistoryDialog::showDetails() { + Object txobj; + uint256 txid; + txid.SetHex(ui->orderHistoryTable->item(ui->orderHistoryTable->currentRow(),6)->text().toStdString()); + std::string strTXText; + + // first of all check if the TX is a pending tx, if so grab details from pending map + PendingMap::iterator it = my_pending.find(txid); + if (it != my_pending.end()) + { + CMPPending *p_pending = &(it->second); + strTXText = "*** THIS TRANSACTION IS UNCONFIRMED ***\n" + p_pending->desc; + } + else + { + // grab details usual way + int pop = populateRPCTransactionObject(txid, &txobj, ""); + if (0<=pop) + { + strTXText = write_string(Value(txobj), false) + "\n"; + } + } + if (!strTXText.empty()) + { + // clean up + string from = ","; + string to = ",\n "; + size_t start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = ":"; + to = " : "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "{"; + to = "{\n "; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "}"; + to = "\n}"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + + QString txText = QString::fromStdString(strTXText); + QDialog *txDlg = new QDialog; + QLayout *dlgLayout = new QVBoxLayout; + dlgLayout->setSpacing(12); + dlgLayout->setMargin(12); + QTextEdit *dlgTextEdit = new QTextEdit; + dlgTextEdit->setText(txText); + dlgTextEdit->setStatusTip("Transaction Information"); + dlgLayout->addWidget(dlgTextEdit); + txDlg->setWindowTitle("Transaction Information"); + QPushButton *closeButton = new QPushButton(tr("&Close")); + closeButton->setDefault(true); + QDialogButtonBox *buttonBox = new QDialogButtonBox; + buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); + dlgLayout->addWidget(buttonBox); + txDlg->setLayout(dlgLayout); + txDlg->resize(700, 360); + connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); + txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed + if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close + } } + diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h index eef11c9a5936b..b029c19916aff 100644 --- a/src/qt/orderhistorydialog.h +++ b/src/qt/orderhistorydialog.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include class OptionsModel; @@ -44,8 +46,8 @@ class OrderHistoryDialog : public QDialog QTableWidgetItem *amountInCell; QTableWidgetItem *txidCell; QLayout *dlgLayout; -// QTextEdit *dlgTextEdit; -// QDialogButtonBox *buttonBox; + QTextEdit *dlgTextEdit; + QDialogButtonBox *buttonBox; QPushButton *closeButton; From 7bdce1ea0a36534fc657b883eed39f9c39618d03 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 1 Dec 2014 20:02:30 -0800 Subject: [PATCH 080/141] add matches to trade info --- src/qt/orderhistorydialog.cpp | 107 +++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp index ebd340108747b..aa9003af7ffc1 100644 --- a/src/qt/orderhistorydialog.cpp +++ b/src/qt/orderhistorydialog.cpp @@ -242,8 +242,8 @@ void OrderHistoryDialog::Update() uint64_t amountForSale = 0; uint64_t amountDesired = 0; string address; - bool divisibleForSale; - bool divisibleDesired; + bool divisibleForSale = false; + bool divisibleDesired = false; Array tradeArray; uint64_t totalBought = 0; uint64_t totalSold = 0; @@ -363,7 +363,7 @@ void OrderHistoryDialog::Update() if(statusText == "Filled") ic = QIcon(":/icons/meta_filled"); if(statusText == "Open") ic = QIcon(":/icons/meta_open"); if(statusText == "Part Filled") ic = QIcon(":/icons/meta_partial"); - + if(!valid) ic = QIcon(":/icons/transaction_invalid"); // add to order history ui->orderHistoryTable->setRowCount(rowcount+1); QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); @@ -456,6 +456,91 @@ void OrderHistoryDialog::showDetails() int pop = populateRPCTransactionObject(txid, &txobj, ""); if (0<=pop) { + Object tradeobj; + CMPMetaDEx temp_metadexoffer; + string senderAddress; + unsigned int propertyId = 0; + CTransaction wtx; + uint256 blockHash = 0; + if (!GetTransaction(txid, wtx, blockHash, true)) { return; } + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, 0, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sa$ + { + if (0<=mp_obj.step1()) + { + senderAddress = mp_obj.getSender(); + if (0 == mp_obj.step2_Value()) + { + propertyId = mp_obj.getProperty(); + } + } + } + // get the amount for sale in this sell offer to see if filled + uint64_t amountForSale = mp_obj.getAmount(); + + // create array of matches + Array tradeArray; + uint64_t totalBought = 0; + uint64_t totalSold = 0; + t_tradelistdb->getMatchingTrades(txid, propertyId, &tradeArray, &totalSold, &totalBought); + + // get action byte + int actionByte = 0; + if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) { actionByte = (int)temp_metadexoffer.getAction(); } + + // everything seems ok, now add status and get an array of matches to add to the object + // work out status + bool orderOpen = isMetaDExOfferActive(txid, propertyId); + bool partialFilled = false; + bool filled = false; + string statusText; + if(totalSold>0) partialFilled = true; + if(totalSold>=amountForSale) filled = true; + statusText = "unknown"; + if((!orderOpen) && (!partialFilled)) statusText = "cancelled"; // offers that are closed but not filled must have been cancelled + if((!orderOpen) && (partialFilled)) statusText = "cancelled part filled"; // offers that are closed but not filled must have been cancelled + if((!orderOpen) && (filled)) statusText = "filled"; // filled offers are closed + if((orderOpen) && (!partialFilled)) statusText = "open"; // offer exists but no matches yet + if((orderOpen) && (partialFilled)) statusText = "open part filled"; // offer exists, some matches but not filled yet + if(actionByte==1) txobj.push_back(Pair("status", statusText)); // no status for cancel txs + + // add cancels array to object and set status as cancelled only if cancel type + if(actionByte != 1) + { + Array cancelArray; + int numberOfCancels = p_txlistdb->getNumberOfMetaDExCancels(txid); + if (0getKeyValue(txid.ToString() + "-C" + to_string(refNumber)); + if (!strValue.empty()) + { + std::vector vstr; + boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); + if (3 <= vstr.size()) + { + uint64_t propId = boost::lexical_cast(vstr[1]); + uint64_t amountUnreserved = boost::lexical_cast(vstr[2]); + cancelTx.push_back(Pair("txid", vstr[0])); + cancelTx.push_back(Pair("propertyid", propId)); + cancelTx.push_back(Pair("amountunreserved", FormatMP(propId, amountUnreserved))); + cancelArray.push_back(cancelTx); + } + } + } + } + txobj.push_back(Pair("cancelledtransactions", cancelArray)); + } + else + { + // if cancelled, show cancellation txid + if((statusText == "cancelled") || (statusText == "cancelled part filled")) { txobj.push_back(Pair("canceltxid", p_txlistdb->findMetaDExCancel(txid).GetHex())); } + // add matches array to object + txobj.push_back(Pair("matches", tradeArray)); // only action 1 offers can have matches + } strTXText = write_string(Value(txobj), false) + "\n"; } } @@ -495,6 +580,22 @@ void OrderHistoryDialog::showDetails() strTXText.replace(start_pos, from.length(), to); start_pos += to.length(); // Handles case where 'to' is a substring of 'from' } + from = "["; + to = "[\n"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + from = "]"; + to = "\n]"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } QString txText = QString::fromStdString(strTXText); QDialog *txDlg = new QDialog; From a5d4dcef3f39e026638129930a6dbb62681bd436 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 2 Dec 2014 11:02:40 -0800 Subject: [PATCH 081/141] Activate pending label --- src/qt/metadexdialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 7fea6d8c2068b..025e07c486475 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -152,12 +152,12 @@ void MetaDExDialog::OrderRefresh() UpdateBuyOffers(); // check for pending transactions, could be more filtered to just trades here bool pending = false; -// for(PendingMap::iterator my_it = my_pending.begin(); my_it != my_pending.end(); ++my_it) -// { + for(PendingMap::iterator my_it = my_pending.begin(); my_it != my_pending.end(); ++my_it) + { // if we get here there are pending transactions in the wallet, flag warning to MetaDEx -// pending = true; -// } -// if(pending) { ui->pendingLabel->setVisible(true); } else { ui->pendingLabel->setVisible(false); } + pending = true; + } + if(pending) { ui->pendingLabel->setVisible(true); } else { ui->pendingLabel->setVisible(false); } } void MetaDExDialog::SwitchMarket() From cbee35082a9c2884a7d48ea313cecadbe460d842 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 2 Dec 2014 11:15:18 -0800 Subject: [PATCH 082/141] Metadex form changes --- src/qt/forms/metadexdialog.ui | 248 ++++++---------------------------- src/qt/metadexdialog.cpp | 5 +- 2 files changed, 42 insertions(+), 211 deletions(-) diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui index 917871472e16e..0eb1160a2a6b6 100644 --- a/src/qt/forms/metadexdialog.ui +++ b/src/qt/forms/metadexdialog.ui @@ -6,7 +6,7 @@ 0 0 - 664 + 704 474 @@ -58,24 +58,8 @@ 10 - 10 + 0 - - - - - 75 - true - - - - Trade MaidSafeCoin (#3) for Mastercoin - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - @@ -85,199 +69,47 @@ 0 - - - - 50 - false - - - - Switch Markets: - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Switch - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - 0 - - - 0 - - - - - - 10 - 75 - true - - - - SPT#3 / MSC : 0.000371 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 4 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 75 - true - - - - 7d: - - - - - + 75 true - - color: red; - - -2.345 (-0.68%) + Trade MaidSafeCoin (#3) for Mastercoin - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + Qt::Horizontal - QSizePolicy::Fixed + QSizePolicy::Expanding - 20 + 10 20 - - - - 75 - true - - - - 24h: - - - - - + - 75 - true + 50 + false - - color: green; - - +1.234 (0.34%) + Switch Markets: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -285,47 +117,43 @@ - - - Qt::Horizontal - - - QSizePolicy::Fixed + + + + 0 + 0 + - + - 20 - 20 + 50 + 0 - - - - - - - 75 - true - - - - 1h: + + + 0 + 0 + - - - - 75 - true - + + + + 0 + 0 + - - color:green; + + + 80 + 0 + - +1.234 (0.33%) + Switch diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 025e07c486475..89a85adcb74c9 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -124,6 +124,8 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : ui->sellList->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->sellList->setSelectionMode(QAbstractItemView::SingleSelection); + ui->pendingLabel->setVisible(false); + connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); connect(ui->buyButton, SIGNAL(clicked()), this, SLOT(buyTrade())); connect(ui->sellButton, SIGNAL(clicked()), this, SLOT(sellTrade())); @@ -462,7 +464,8 @@ void MetaDExDialog::FullRefresh() // update the balances UpdateSellAddress(); UpdateBuyAddress(); - + UpdateBuyOffers(); + UpdateSellOffers(); // silly sizing // QRect rect = ui->openOrders->geometry(); // int tableHeight = 2 + ui->openOrders->horizontalHeader()->height(); From d74b224ea7f36099100ac9622d2e8f2630c82060 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 2 Dec 2014 11:23:56 -0800 Subject: [PATCH 083/141] Fix prop name display on metadex form --- src/qt/metadexdialog.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 89a85adcb74c9..26e0dc69ec3e9 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -378,8 +378,17 @@ void MetaDExDialog::FullRefresh() { // populate from address selector unsigned int propertyId = global_metadex_market; + string propNameStr = getPropertyName(propertyId); bool testeco = false; if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; + if(testeco) + { + ui->marketLabel->setText(QString::fromStdString("Trade " + propNameStr + " (#" + FormatIndivisibleMP(propertyId) + ") for Test Mastercoin")); + } + else + { + ui->marketLabel->setText(QString::fromStdString("Trade " + propNameStr + " (#" + FormatIndivisibleMP(propertyId) + ") for Mastercoin")); + } LOCK(cs_tally); // get currently selected addresses From b47af52360ef521f49c3b7c88eca83413aae7017 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 2 Dec 2014 12:34:46 -0800 Subject: [PATCH 084/141] Fix for prices --- src/mastercore.cpp | 9 +++++++++ src/mastercore.h | 5 +++++ src/qt/metadexdialog.cpp | 33 +++++++++++++++++++++------------ src/qt/metadexdialog.h | 3 +++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 87bc6c7d31ac9..1d6fb3d8cac45 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -320,6 +320,15 @@ bool isNonMainNet() return (TestNet() || RegTest()); } +string FormatPriceMP(double n) +{ + string str = strprintf("%lf", n); + // clean up trailing zeros - good for RPC not so much for UI + str.erase ( str.find_last_not_of('0') + 1, std::string::npos ); + if (str.length() > 0) { std::string::iterator it = str.end() - 1; if (*it == '.') { str.erase(it); } } //get rid of trailing dot if non decimal +return str; +} + string FormatDivisibleShortMP(int64_t n) { int64_t n_abs = (n > 0 ? n : -n); diff --git a/src/mastercore.h b/src/mastercore.h index b44dc0e082ed9..1d97d32bdd0dd 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -132,6 +132,10 @@ enum FILETYPES { #define OMNI_PROPERTY_MSC 1 #define OMNI_PROPERTY_TMSC 2 +#include +using boost::multiprecision::cpp_dec_float_100; +typedef cpp_dec_float_100 XDOUBLE; + int mp_LogPrintStr(const std::string &str); /* When we switch to C++11, this can be switched to variadic templates instead @@ -177,6 +181,7 @@ TINYFORMAT_FOREACH_ARGNUM(MP_MAKE_ERROR_AND_LOG_FUNC) //--- CUT HERE --- // forward declarations +std::string FormatPriceMP(double n); std::string FormatDivisibleMP(int64_t n, bool fSign = false); std::string FormatDivisibleShortMP(int64_t); std::string FormatMP(unsigned int, int64_t n, bool fSign = false); diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 26e0dc69ec3e9..e5b70d9f3270b 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -56,6 +56,15 @@ using namespace leveldb; #include "mastercore_sp.h" #include "mastercore_parse_string.h" +#include +#include +#include + +using boost::multiprecision::int128_t; +using boost::multiprecision::cpp_int; +using boost::multiprecision::cpp_dec_float; +using boost::multiprecision::cpp_dec_float_100; + #include #include #include @@ -225,7 +234,7 @@ void MetaDExDialog::UpdateSellOffers() md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { - XDOUBLE price = (it->first); + //XDOUBLE price = (it->first); int64_t available = 0; int64_t total = 0; bool includesMe = false; @@ -236,19 +245,19 @@ void MetaDExDialog::UpdateSellOffers() CMPMetaDEx obj = *it; if ( ((testeco) && (obj.getDesProperty() == 2)) || ((!testeco) && (obj.getDesProperty() == 1)) ) { - available += obj.getAmountDesired(); - total += obj.getAmountForSale(); + available += obj.getAmountForSale(); + total += obj.getAmountDesired(); if(IsMyAddress(obj.getAddr())) includesMe = true; } } - // done checking this price, if there are any available/total add to pricebook if ((available > 0) && (total > 0)) { // add to pricebook - QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); - QString tstr = QString::fromStdString(FormatDivisibleMP(available)); - QString mstr = QString::fromStdString(FormatDivisibleMP(total)); + double price = (double)total/(double)available; + QString pstr = QString::fromStdString(FormatPriceMP(price)); //(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); + QString tstr = QString::fromStdString(FormatDivisibleShortMP(available)); + QString mstr = QString::fromStdString(FormatDivisibleShortMP(total)); if (!ui->sellList) { printf("metadex dialog error\n"); return; } ui->sellList->setRowCount(rowcount+2); ui->sellList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); @@ -286,7 +295,7 @@ void MetaDExDialog::UpdateBuyOffers() md_PricesMap & prices = my_it->second; for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) { - XDOUBLE price = (1/it->first); + //XDOUBLE price = (1/it->first); double available = 0; double total = 0; bool includesMe = false; @@ -306,9 +315,10 @@ void MetaDExDialog::UpdateBuyOffers() if ((available > 0) && (total > 0)) { // add to pricebook - QString pstr = QString::fromStdString(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); - QString tstr = QString::fromStdString(FormatDivisibleMP(available)); - QString mstr = QString::fromStdString(FormatDivisibleMP(total)); + double price = (double)total/(double)available; + QString pstr = QString::fromStdString(FormatPriceMP(price)); + QString tstr = QString::fromStdString(FormatDivisibleShortMP(available)); + QString mstr = QString::fromStdString(FormatDivisibleShortMP(total)); if (!ui->buyList) { printf("metadex dialog error\n"); return; } ui->buyList->setRowCount(rowcount+2); ui->buyList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); @@ -469,7 +479,6 @@ void MetaDExDialog::FullRefresh() if (sellIdx != -1) { ui->sellAddressCombo->setCurrentIndex(sellIdx); } // -1 means the new prop doesn't have the previously selected address int buyIdx = ui->buyAddressCombo->findText(currentSetBuyAddress); if (buyIdx != -1) { ui->buyAddressCombo->setCurrentIndex(buyIdx); } // -1 means the new prop doesn't have the previously selected address - // update the balances UpdateSellAddress(); UpdateBuyAddress(); diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h index e91ebd761390c..e14ad0077183e 100644 --- a/src/qt/metadexdialog.h +++ b/src/qt/metadexdialog.h @@ -9,6 +9,9 @@ #include #include +#include + +using boost::multiprecision::cpp_dec_float_100; class OptionsModel; From e6a533df35f45595e7da773766b386acb82788d4 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 10:27:10 -0800 Subject: [PATCH 085/141] Fix alignment --- src/qt/metadexdialog.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index e5b70d9f3270b..4d4071a46d7e1 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -263,6 +263,10 @@ void MetaDExDialog::UpdateSellOffers() ui->sellList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); ui->sellList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); ui->sellList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + ui->sellList->item(rowcount, 0)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + ui->sellList->item(rowcount, 1)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + ui->sellList->item(rowcount, 2)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + if(includesMe) { QFont font; @@ -324,6 +328,10 @@ void MetaDExDialog::UpdateBuyOffers() ui->buyList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); ui->buyList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); ui->buyList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); + ui->buyList->item(rowcount, 0)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + ui->buyList->item(rowcount, 1)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + ui->buyList->item(rowcount, 2)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + if(includesMe) { QFont font; From 8f7ad01fc091c914d6b8c19a1a069bac89c2cfd7 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 11:19:30 -0800 Subject: [PATCH 086/141] Add --startclean option to delete persistence --- src/mastercore.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index da3fd2ea925f7..2d1d55a11ba46 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -2442,6 +2442,29 @@ int mastercore_init() exodus_address = exodus_testnet; }*/ + // check for --startclean option and delete MP_ folders if present + if (GetBoolArg("-startclean", false)) + { + try + { + boost::filesystem::path persistPath = GetDataDir() / "MP_persist"; + boost::filesystem::path txlistPath = GetDataDir() / "MP_txlist"; + boost::filesystem::path tradePath = GetDataDir() / "MP_tradelist"; + boost::filesystem::path spPath = GetDataDir() / "MP_spinfo"; +// string stoPath = GetDataDir() / "MP_sto"; + if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); + if (boost::filesystem::exists(txlistPath)) boost::filesystem::remove_all(txlistPath); + if (boost::filesystem::exists(tradePath)) boost::filesystem::remove_all(tradePath); + if (boost::filesystem::exists(spPath)) boost::filesystem::remove_all(spPath); +// boost::filesystem::remove_all(stoPath); + } + catch(boost::filesystem::filesystem_error const & e) + { + file_log("Exception deleting folders for --startclean option.\n"); + printf("Exception deleting folders for --startclean option.\n"); + } + } + t_tradelistdb = new CMPTradeList(GetDataDir() / "MP_tradelist", 1<<20, false, fReindex); p_txlistdb = new CMPTxList(GetDataDir() / "MP_txlist", 1<<20, false, fReindex); _my_sps = new CMPSPInfo(GetDataDir() / "MP_spinfo"); From ed1274f9b607e6c136fbbb5e67fbf63b60d76139 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 11:49:06 -0800 Subject: [PATCH 087/141] Add stolistdb for levelDB storage of STO receipts --- src/mastercore.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++-- src/mastercore.h | 41 ++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 2d1d55a11ba46..4fa7c4b9e4083 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -152,6 +152,7 @@ static const int txRestrictionsRules[][3] = { CMPTxList *mastercore::p_txlistdb; CMPTradeList *mastercore::t_tradelistdb; +CMPSTOList *mastercore::s_stolistdb; // a copy from main.cpp -- unfortunately that one is in a private namespace int mastercore::GetHeight() @@ -2451,12 +2452,12 @@ int mastercore_init() boost::filesystem::path txlistPath = GetDataDir() / "MP_txlist"; boost::filesystem::path tradePath = GetDataDir() / "MP_tradelist"; boost::filesystem::path spPath = GetDataDir() / "MP_spinfo"; -// string stoPath = GetDataDir() / "MP_sto"; + boost::filesystem::path stoPath = GetDataDir() / "MP_sto"; if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); if (boost::filesystem::exists(txlistPath)) boost::filesystem::remove_all(txlistPath); if (boost::filesystem::exists(tradePath)) boost::filesystem::remove_all(tradePath); if (boost::filesystem::exists(spPath)) boost::filesystem::remove_all(spPath); -// boost::filesystem::remove_all(stoPath); + if (boost::filesystem::exists(stoPath)) boost::filesystem::remove_all(stoPath); } catch(boost::filesystem::filesystem_error const & e) { @@ -2466,6 +2467,7 @@ int mastercore_init() } t_tradelistdb = new CMPTradeList(GetDataDir() / "MP_tradelist", 1<<20, false, fReindex); + s_stolistdb = new CMPSTOList(GetDataDir() / "MP_stolist", 1<<20, false, fReindex); p_txlistdb = new CMPTxList(GetDataDir() / "MP_txlist", 1<<20, false, fReindex); _my_sps = new CMPSPInfo(GetDataDir() / "MP_spinfo"); MPPersistencePath = GetDataDir() / "MP_persist"; @@ -2563,6 +2565,10 @@ int mastercore_shutdown() { delete t_tradelistdb; t_tradelistdb = NULL; } + if (s_stolistdb) + { + delete s_stolistdb; s_stolistdb = NULL; + } // if (mp_fp) { @@ -3520,6 +3526,69 @@ unsigned int n_found = 0; return (n_found); } +// MPSTOList here +void CMPSTOList::printAll() +{ + int count = 0; + Slice skey, svalue; + + readoptions.fill_cache = false; + + Iterator* it = sdb->NewIterator(readoptions); + + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + svalue = it->value(); + ++count; + printf("entry #%8d= %s:%s\n", count, skey.ToString().c_str(), svalue.ToString().c_str()); + } + + delete it; +} + +void CMPSTOList::printStats() +{ + file_log("CMPSTOList stats: tWritten= %d , tRead= %d\n", sWritten, sRead); +} + +// delete any STO receipts after blockNum +int CMPSTOList::deleteAboveBlock(int blockNum) +{ + leveldb::Slice skey, svalue; + unsigned int count = 0; + std::vector vstr; + int block; + unsigned int n_found = 0; + leveldb::Iterator* it = sdb->NewIterator(iteroptions); + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + svalue = it->value(); + ++count; + string strvalue = it->value().ToString(); + boost::split(vstr, strvalue, boost::is_any_of(":"), token_compress_on); + // only care about the block number/height here + if (7 == vstr.size()) + { + block = atoi(vstr[6]); + + if (block >= blockNum) + { + ++n_found; + file_log("%s() DELETING FROM STODB: %s=%s\n", __FUNCTION__, skey.ToString().c_str(), svalue.ToString().c_str()); + sdb->Delete(writeoptions, skey); + } + } + } + + printf("%s(%d); stodb n_found= %d\n", __FUNCTION__, blockNum, n_found); + + delete it; + + return (n_found); +} + // MPTradeList here bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalSold, uint64_t *totalBought) { diff --git a/src/mastercore.h b/src/mastercore.h index 019cbdc8dad5e..32d3d785d3a70 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -313,6 +313,46 @@ typedef struct } }; +/* leveldb-based storage for sto recipients */ +class CMPSTOList +{ + protected: + // datebase options reused from MPTxList + leveldb::Options options; + leveldb::ReadOptions readoptions; + leveldb::ReadOptions iteroptions; + leveldb::WriteOptions writeoptions; + leveldb::WriteOptions syncoptions; + leveldb::DB *sdb; + // statistics + unsigned int sWritten; + unsigned int sRead; + +public: + CMPSTOList(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe):sWritten(0),sRead(0) + { + options.paranoid_checks = true; + options.create_if_missing = true; + readoptions.verify_checksums = true; + iteroptions.verify_checksums = true; + iteroptions.fill_cache = false; + syncoptions.sync = true; + leveldb::Status status = leveldb::DB::Open(options, path.string(), &sdb); + printf("%s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } + + ~CMPSTOList() + { + delete sdb; + sdb = NULL; + } + + int deleteAboveBlock(int blockNum); +// bool exists(const uint256 &txid); + void printStats(); + void printAll(); +}; + /* leveldb-based storage for trade history - trades will be listed here atomically with key txid1:txid2 */ class CMPTradeList { @@ -471,6 +511,7 @@ namespace mastercore extern std::map mp_tally_map; extern CMPTxList *p_txlistdb; extern CMPTradeList *t_tradelistdb; +extern CMPSTOList *s_stolistdb; typedef std::map PendingMap; extern PendingMap my_pending; From 7f1c3ae057531511f7e8298f3f7bf9957c082c63 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 12:13:22 -0800 Subject: [PATCH 088/141] add RecordSTOReceive function to CMPSTOList class --- src/mastercore.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++ src/mastercore.h | 3 ++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 4fa7c4b9e4083..70fba92853257 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3527,6 +3527,60 @@ unsigned int n_found = 0; } // MPSTOList here +bool CMPSTOList::exists(string address) +{ + if (!sdb) return false; + +string strValue; +Status status = sdb->Get(readoptions, address, &strValue); + + if (!status.ok()) + { + if (status.IsNotFound()) return false; + } + + return true; +} + +void CMPSTOList::recordSTOReceive(string address, const uint256 &txid, int nBlock, unsigned int propertyId, uint64_t amount) +{ + if (!sdb) return; + + bool addressExists = s_stolistdb->exists(address); + if (addressExists) + { + //retrieve existing record + std::vector vstr; + string strValue; + Status status = sdb->Get(readoptions, address, &strValue); + if (status.ok()) + { + // add details to record + const string key = address; + const string newValue = strprintf("%s:%d:%u:%lu,", txid.ToString(), nBlock, propertyId, amount); + strValue += newValue; + // write updated record + Status status; + if (sdb) + { + status = sdb->Put(writeoptions, key, strValue); + file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } + } + else + { + const string key = address; + const string value = strprintf("%s:%d:%u:%lu,", txid.ToString(), nBlock, propertyId, amount); + Status status; + if (sdb) + { + status = sdb->Put(writeoptions, key, value); + file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } + } + } +} + void CMPSTOList::printAll() { int count = 0; diff --git a/src/mastercore.h b/src/mastercore.h index 32d3d785d3a70..ead7ced3d7865 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -348,9 +348,10 @@ class CMPSTOList } int deleteAboveBlock(int blockNum); -// bool exists(const uint256 &txid); + bool exists(string address); void printStats(); void printAll(); + void recordSTOReceive(std::string, const uint256&, int, unsigned int, uint64_t); }; /* leveldb-based storage for trade history - trades will be listed here atomically with key txid1:txid2 */ From ac7925b6d516e8a2476c17711abe97263badb747 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 12:50:27 -0800 Subject: [PATCH 089/141] Add recording of STO receipt --- src/mastercore.cpp | 21 ++++++++++++--------- src/mastercore_rpc.cpp | 4 ++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 70fba92853257..0fa090d96d905 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3567,16 +3567,16 @@ void CMPSTOList::recordSTOReceive(string address, const uint256 &txid, int nBloc file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); } } - else + } + else + { + const string key = address; + const string value = strprintf("%s:%d:%u:%lu,", txid.ToString(), nBlock, propertyId, amount); + Status status; + if (sdb) { - const string key = address; - const string value = strprintf("%s:%d:%u:%lu,", txid.ToString(), nBlock, propertyId, amount); - Status status; - if (sdb) - { - status = sdb->Put(writeoptions, key, value); - file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); - } + status = sdb->Put(writeoptions, key, value); + file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); } } } @@ -4572,6 +4572,9 @@ int rc = PKT_ERROR_STO -1000; update_tally_map(address, property, will_really_receive, BALANCE); + // add to stodb + s_stolistdb->recordSTOReceive(address, txid, block, property, will_really_receive); + if (sent_so_far >= nValue) { file_log("SendToOwners: DONE HERE : those who could get paid got paid, SOME DID NOT, but that's ok\n"); diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 545e78cb702cd..514958f6f34a4 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -182,6 +182,10 @@ int extra2 = 0, extra3 = 0; t_tradelistdb->printStats(); break; + case 8: + // display the STO receive list + s_stolistdb->printAll(); + s_stolistdb->printStats(); } return GetHeight(); From 78383ba19c376ce38692c83917b2907e0a38180c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 16:40:56 -0800 Subject: [PATCH 090/141] Add getsto_MP RPC call --- src/mastercore_rpc.cpp | 5 +++++ src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + 3 files changed, 7 insertions(+) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 514958f6f34a4..30d9d70a6131f 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1962,6 +1962,11 @@ Value getinfo_MP(const Array& params, bool fHelp) return infoResponse; } +Value getsto_MP(const Array& params, bool fHelp) +{ + +} + Value gettrade_MP(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index ec48df9aeb2bb..1a8db1796addb 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -329,6 +329,7 @@ static const CRPCCommand vRPCCommands[] = { "getactivedexsells_MP", &getactivedexsells_MP, false, false, true }, { "getactivecrowdsales_MP", &getactivecrowdsales_MP, false, false, true }, { "trade_MP", &trade_MP, false, false, true }, + { "getsto_MP", &getsto_MP, false, false, true }, { "getorderbook_MP", &getorderbook_MP, false, false, true }, { "gettradessince_MP", &gettradessince_MP, false, false, true }, { "getopenorders_MP", &getopenorders_MP, false, false, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 353e0d08b73cf..b1bd249ff0bdd 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -211,4 +211,5 @@ extern json_spirit::Value gettradehistory_MP(const json_spirit::Array& params, b extern json_spirit::Value listtransactions_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value listblocktransactions_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp extern json_spirit::Value getinfo_MP(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getsto_MP(const json_spirit::Array& params, bool fHelp); #endif From 42c6838f5055d463c3c069fc6996e2ecb515f1a0 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 16:54:59 -0800 Subject: [PATCH 091/141] Code up getsto_MP RPC call --- src/mastercore_rpc.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 30d9d70a6131f..53a199bf31661 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1964,7 +1964,64 @@ Value getinfo_MP(const Array& params, bool fHelp) Value getsto_MP(const Array& params, bool fHelp) { + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getsto_MP \"txid\" \"recipientfilter\"\n" + "\nGet information and recipients of send to owners transaction \n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "2. \"recipientfilter\" (string, optional) The recipient address filter (wallet by default, \"*\" for all)\n" + "\nResult:\n" + "{\n" + " \"txid\" : \"transactionid\", (string) The transaction id\n" + + HelpExampleCli("getsto_MP", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + + HelpExampleRpc("getsto_MP", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + ); + uint256 hash; + hash.SetHex(params[0].get_str()); + string filterAddress = ""; + if (params.size() == 2) filterAddress=params[1].get_str(); + Object txobj; + CTransaction wtx; + uint256 blockHash = 0; + if (!GetTransaction(hash, wtx, blockHash, true)) { return MP_TX_NOT_FOUND; } + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, 0, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for safety + { + // make a request to new RPC populator function to populate a transaction object + int populateResult = populateRPCTransactionObject(hash, &txobj); + // check the response, throw any error codes if false + if (0>populateResult) + { + // TODO: consider throwing other error codes, check back with Bitcoin Core + switch (populateResult) + { + case MP_TX_NOT_FOUND: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + case MP_TX_UNCONFIRMED: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unconfirmed transactions are not supported"); + case MP_BLOCK_NOT_IN_CHAIN: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not part of the active chain"); + case MP_CROWDSALE_WITHOUT_PROPERTY: + throw JSONRPCError(RPC_INTERNAL_ERROR, "Potential database corruption: \ + \"Crowdsale Purchase\" without valid property identifier"); + case MP_INVALID_TX_IN_DB_FOUND: + throw JSONRPCError(RPC_INTERNAL_ERROR, "Potential database corruption: Invalid transaction found"); + case MP_TX_IS_NOT_MASTER_PROTOCOL: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); + } + } + // create array of recipients + Array receiveArray; + s_stolistdb->getRecipients(hash, filterAddress, &receiveArray); + // add matches array to object + txobj.push_back(Pair("recipients", receiveArray)); + } + + // return object + return txobj; } Value gettrade_MP(const Array& params, bool fHelp) From 1f733b555fc6437660d06aeed6238901bdb2e91c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 17:07:50 -0800 Subject: [PATCH 092/141] Prep getRecipients function --- src/mastercore.cpp | 5 +++++ src/mastercore.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 0fa090d96d905..4f7dd05f9a325 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3527,6 +3527,11 @@ unsigned int n_found = 0; } // MPSTOList here +void CMPSTOList::getRecipients(const uint256 hash, string filterAddress, Array *receiveArray) +{ + +} + bool CMPSTOList::exists(string address) { if (!sdb) return false; diff --git a/src/mastercore.h b/src/mastercore.h index ead7ced3d7865..2e872556fb8bd 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -347,6 +347,7 @@ class CMPSTOList sdb = NULL; } + void getRecipients(const uint256 hash, string filterAddress, Array *receiveArray); int deleteAboveBlock(int blockNum); bool exists(string address); void printStats(); From 02453df52d095347edf2b56e20655c7fdb28ff42 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 17:42:01 -0800 Subject: [PATCH 093/141] Coding out getRecipients function for sdb --- src/mastercore.cpp | 67 +++++++++++++++++++++++++++++++++++++++++- src/mastercore.h | 2 +- src/mastercore_rpc.cpp | 14 ++++++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 4f7dd05f9a325..c407c1efca748 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3527,9 +3527,74 @@ unsigned int n_found = 0; } // MPSTOList here -void CMPSTOList::getRecipients(const uint256 hash, string filterAddress, Array *receiveArray) +void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible) { + if (!sdb) return; + + bool filter = true; //default + bool filterByWallet = true; //default + bool filterByAddress = false; //default + + if (filterAddress == "*") filter = false; + if ((filterAddress != "") && (filterAddress != "*")) { filterByWallet = false; filterByAddress = true; } + + // iterate through SDB, dropping all records where key is not filterAddress (if filtering) + int count = 0; + Slice skey, svalue; + readoptions.fill_cache = false; + Iterator* it = sdb->NewIterator(readoptions); + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + string recipientAddress = skey.ToString(); + if(filter) + { + if( ( (filterByAddress) && (filterAddress == recipientAddress) ) || ( (filterByWallet) && (IsMyAddress(recipientAddress)) ) ) + { } else { continue; } // move on if no filter match + } + svalue = it->value(); + string strValue = svalue.ToString(); + // see if txid is in the data + size_t txidMatch = strValue.find(txid.ToString()); + if(txidMatch!=std::string::npos) + { + // the txid exists inside the data, this address was a recipient of this STO, add the details + std::vector vstr; + boost::split(vstr, strValue, boost::is_any_of(","), token_compress_on); + for(uint32_t i = 0; i svstr; + boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); + if(4 == svstr.size()) + { + //add data to array + uint64_t amount = 0; + try + { + amount = boost::lexical_cast(vstr[3]); + } catch (const boost::bad_lexical_cast &e) + { + file_log("DEBUG STO - error in converting values from leveldb\n"); + return; //(something went wrong) + } + Object recipient; + recipient.push_back(Pair("address", recipientAddress)); + if(divisible) + { + recipient.push_back(Pair("amount", FormatDivisibleMP(amount))); + } + else + { + recipient.push_back(Pair("amount", FormatIndivisibleMP(amount))); + } + recipientArray->push_back(recipient); + ++count; + } + } + } + } + delete it; } bool CMPSTOList::exists(string address) diff --git a/src/mastercore.h b/src/mastercore.h index 2e872556fb8bd..ef6c7e4482450 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -347,7 +347,7 @@ class CMPSTOList sdb = NULL; } - void getRecipients(const uint256 hash, string filterAddress, Array *receiveArray); + void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible); int deleteAboveBlock(int blockNum); bool exists(string address); void printStats(); diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 53a199bf31661..e285fa4dba88a 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1986,10 +1986,22 @@ Value getsto_MP(const Array& params, bool fHelp) CTransaction wtx; uint256 blockHash = 0; if (!GetTransaction(hash, wtx, blockHash, true)) { return MP_TX_NOT_FOUND; } + uint64_t propertyId = 0; CMPTransaction mp_obj; int parseRC = parseTransaction(true, wtx, 0, 0, &mp_obj); if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for safety { + if (0<=mp_obj.step1()) + { + if (0 == mp_obj.step2_Value()) + { + propertyId = mp_obj.getProperty(); + } + } + if (propertyId == 0) // something went wrong, couldn't decode property ID - bad packet? + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); + + bool divisible = isPropertyDivisible(propertyId); // make a request to new RPC populator function to populate a transaction object int populateResult = populateRPCTransactionObject(hash, &txobj); // check the response, throw any error codes if false @@ -2015,7 +2027,7 @@ Value getsto_MP(const Array& params, bool fHelp) } // create array of recipients Array receiveArray; - s_stolistdb->getRecipients(hash, filterAddress, &receiveArray); + s_stolistdb->getRecipients(hash, filterAddress, &receiveArray, divisible); // add matches array to object txobj.push_back(Pair("recipients", receiveArray)); } From 97fe01ba772eeb42dc20618f5391f9b461654315 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 18:02:17 -0800 Subject: [PATCH 094/141] Bug fixes for getsto_MP --- src/mastercore.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index c407c1efca748..de1253411f7fe 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3567,34 +3567,39 @@ void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array * boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); if(4 == svstr.size()) { - //add data to array - uint64_t amount = 0; - try + if(svstr[0] == txid.ToString()) { - amount = boost::lexical_cast(vstr[3]); - } catch (const boost::bad_lexical_cast &e) - { - file_log("DEBUG STO - error in converting values from leveldb\n"); - return; //(something went wrong) - } - Object recipient; - recipient.push_back(Pair("address", recipientAddress)); - if(divisible) - { - recipient.push_back(Pair("amount", FormatDivisibleMP(amount))); - } - else - { - recipient.push_back(Pair("amount", FormatIndivisibleMP(amount))); + //add data to array + uint64_t amount = 0; + try + { + amount = boost::lexical_cast(svstr[3]); + } catch (const boost::bad_lexical_cast &e) + { + file_log("DEBUG STO - error in converting values from leveldb\n"); + delete it; + return; //(something went wrong) + } + Object recipient; + recipient.push_back(Pair("address", recipientAddress)); + if(divisible) + { + recipient.push_back(Pair("amount", FormatDivisibleMP(amount))); + } + else + { + recipient.push_back(Pair("amount", FormatIndivisibleMP(amount))); + } + recipientArray->push_back(recipient); + ++count; } - recipientArray->push_back(recipient); - ++count; } } } } delete it; + return; } bool CMPSTOList::exists(string address) From 6c25eb10ca9beaeacbd64aa0dba7c1a1f47710b5 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 18:30:10 -0800 Subject: [PATCH 095/141] Couple minor fixes to startclean --- src/mastercore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index de1253411f7fe..efe3c826c564e 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -2452,7 +2452,7 @@ int mastercore_init() boost::filesystem::path txlistPath = GetDataDir() / "MP_txlist"; boost::filesystem::path tradePath = GetDataDir() / "MP_tradelist"; boost::filesystem::path spPath = GetDataDir() / "MP_spinfo"; - boost::filesystem::path stoPath = GetDataDir() / "MP_sto"; + boost::filesystem::path stoPath = GetDataDir() / "MP_stolist"; if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); if (boost::filesystem::exists(txlistPath)) boost::filesystem::remove_all(txlistPath); if (boost::filesystem::exists(tradePath)) boost::filesystem::remove_all(tradePath); @@ -4000,6 +4000,7 @@ int mastercore_handler_block_begin(int nBlockPrev, CBlockIndex const * pBlockInd if(!readPersistence()) clear_all_state(); p_txlistdb->isMPinBlockRange(pBlockIndex->nHeight, reorgRecoveryMaxHeight, true); t_tradelistdb->deleteAboveBlock(pBlockIndex->nHeight); + s_stolistdb->deleteAboveBlock(pBlockIndex->nHeight); reorgRecoveryMaxHeight = 0; From cec9d5b2b0c76abb477d093424acd5929cc6ee20 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 4 Dec 2014 19:36:42 -0800 Subject: [PATCH 096/141] Fix STO deleteafterblock --- src/mastercore.cpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index efe3c826c564e..183c24c9e2f11 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3631,6 +3631,10 @@ void CMPSTOList::recordSTOReceive(string address, const uint256 &txid, int nBloc if (status.ok()) { // add details to record + // see if we are overwriting (check) + size_t txidMatch = strValue.find(txid.ToString()); + if(txidMatch!=std::string::npos) file_log("STODEBUG : Duplicating entry for %s : %s\n",address,txid.ToString()); + const string key = address; const string newValue = strprintf("%s:%d:%u:%lu,", txid.ToString(), nBlock, propertyId, amount); strValue += newValue; @@ -3687,27 +3691,40 @@ int CMPSTOList::deleteAboveBlock(int blockNum) leveldb::Slice skey, svalue; unsigned int count = 0; std::vector vstr; - int block; unsigned int n_found = 0; leveldb::Iterator* it = sdb->NewIterator(iteroptions); for(it->SeekToFirst(); it->Valid(); it->Next()) { skey = it->key(); + string address = skey.ToString(); svalue = it->value(); ++count; string strvalue = it->value().ToString(); - boost::split(vstr, strvalue, boost::is_any_of(":"), token_compress_on); - // only care about the block number/height here - if (7 == vstr.size()) + boost::split(vstr, strvalue, boost::is_any_of(","), token_compress_on); + string newValue = ""; + bool needsUpdate = false; + for(uint32_t i = 0; i svstr; + boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); + if(4 == svstr.size()) + { + if(atoi(svstr[1]) <= blockNum) { newValue += vstr[i]; } else { needsUpdate = true; } // add back to new key + } + } - if (block >= blockNum) - { + if(needsUpdate) + { ++n_found; - file_log("%s() DELETING FROM STODB: %s=%s\n", __FUNCTION__, skey.ToString().c_str(), svalue.ToString().c_str()); - sdb->Delete(writeoptions, skey); - } + const string key = address; + // write updated record + Status status; + if (sdb) + { + status = sdb->Put(writeoptions, key, newValue); + file_log("DEBUG STO - rewriting STO data after reorg\n"); + file_log("STODBDEBUG : %s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } } } From d4f4b8b679de8e4b7a83689eb524e7ac3b310a33 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 16:01:32 -0800 Subject: [PATCH 097/141] Disable MetaDEx functionality in UI, next release is STO --- src/qt/Makefile.am | 12 ------------ src/qt/bitcoingui.cpp | 16 ++++++++-------- src/qt/metadexdialog.cpp | 1 - src/qt/walletmodel.cpp | 6 +++--- src/qt/walletview.cpp | 16 +++++++++------- src/qt/walletview.h | 8 ++++---- 6 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 5134dc6f3cdcd..519e042c5a0c0 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -101,10 +101,7 @@ QT_FORMS_UI = \ forms/sendcoinsdialog.ui \ forms/sendcoinsentry.ui \ forms/sendmpdialog.ui \ - forms/orderhistorydialog.ui \ forms/txhistorydialog.ui \ - forms/metadexcanceldialog.ui \ - forms/metadexdialog.ui \ forms/lookupspdialog.ui \ forms/lookupaddressdialog.ui \ forms/lookuptxdialog.ui \ @@ -144,9 +141,6 @@ QT_MOC_CPP = \ moc_sendcoinsdialog.cpp \ moc_sendcoinsentry.cpp \ moc_sendmpdialog.cpp \ - moc_metadexdialog.cpp \ - moc_metadexcanceldialog.cpp \ - moc_orderhistorydialog.cpp \ moc_txhistorydialog.cpp \ moc_lookupspdialog.cpp \ moc_lookupaddressdialog.cpp \ @@ -217,9 +211,6 @@ BITCOIN_QT_H = \ sendcoinsdialog.h \ sendcoinsentry.h \ sendmpdialog.h \ - metadexdialog.h \ - metadexcanceldialog.h \ - orderhistorydialog.h \ txhistorydialog.h \ lookupspdialog.h \ lookupaddressdialog.h \ @@ -341,9 +332,6 @@ BITCOIN_QT_CPP += \ sendcoinsdialog.cpp \ sendcoinsentry.cpp \ sendmpdialog.cpp \ - metadexcanceldialog.cpp \ - metadexdialog.cpp \ - orderhistorydialog.cpp \ txhistorydialog.cpp \ lookupspdialog.cpp \ lookupaddressdialog.cpp \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 49ee3f63d7ba7..b156dd47bfb63 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -252,7 +252,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) exchangeAction->setToolTip(exchangeAction->statusTip()); exchangeAction->setCheckable(true); exchangeAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); - tabGroup->addAction(exchangeAction); +// tabGroup->addAction(exchangeAction); smartPropertyAction = new QAction(QIcon(":/icons/smartproperty"), tr("Smart &Property"), this); smartPropertyAction->setStatusTip(tr("Lookup and interact with Master Protocol Smart Properties")); @@ -285,10 +285,10 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); - connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); - connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(gotoSmartPropertyPage())); - connect(exchangeAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); - connect(exchangeAction, SIGNAL(triggered()), this, SLOT(gotoExchangePage())); +// connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); +// connect(smartPropertyAction, SIGNAL(triggered()), this, SLOT(gotoSmartPropertyPage())); +// connect(exchangeAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); +// connect(exchangeAction, SIGNAL(triggered()), this, SLOT(gotoExchangePage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); connect(toolboxAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); @@ -422,7 +422,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(balancesAction); toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); - toolbar->addAction(exchangeAction); +// toolbar->addAction(exchangeAction); // toolbar->addAction(smartPropertyAction); toolbar->addAction(historyAction); toolbar->addAction(toolboxAction); @@ -490,8 +490,8 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) balancesAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); - exchangeAction->setEnabled(enabled); - smartPropertyAction->setEnabled(enabled); +// exchangeAction->setEnabled(enabled); +// smartPropertyAction->setEnabled(enabled); historyAction->setEnabled(enabled); toolboxAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index 4d4071a46d7e1..bb10fa0338e97 100644 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -77,7 +77,6 @@ MetaDExDialog::MetaDExDialog(QWidget *parent) : { ui->setupUi(this); this->model = model; - //open global_metadex_market = 3; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index d9477a9f27447..e64cf1e70389a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -104,7 +104,7 @@ void WalletModel::updateStatus() void WalletModel::forceUpdateBalances() { - boost::timer t; + // boost::timer t; // Get required locks upfront. This avoids the GUI from getting stuck on // periodical polls if the core is holding the locks for a longer time - // for example, during a wallet rescan. @@ -129,9 +129,9 @@ void WalletModel::forceUpdateBalances() // force everything to be updated emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); if(transactionTableModel) transactionTableModel->updateConfirmations(); - printf("DEBUG: forceUpdate took"); + /* printf("DEBUG: forceUpdate took"); std::cout << t.elapsed() << std::endl; - printf("\n"); + printf("\n"); */ } void WalletModel::pollBalanceChanged() diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index ebbd170e2bc8f..771c3770fc754 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -17,14 +17,14 @@ #include "lookupspdialog.h" #include "lookuptxdialog.h" #include "lookupaddressdialog.h" -#include "metadexcanceldialog.h" -#include "metadexdialog.h" +//#include "metadexcanceldialog.h" +//#include "metadexdialog.h" #include "signverifymessagedialog.h" #include "transactiontablemodel.h" #include "transactionview.h" #include "balancesview.h" #include "walletmodel.h" -#include "orderhistorydialog.h" +//#include "orderhistorydialog.h" #include "txhistorydialog.h" #include "ui_interface.h" @@ -107,6 +107,7 @@ WalletView::WalletView(QWidget *parent): sendCoinsPage->setLayout(svbox); // exchange page + /* no MetaDEx in this ver exchangePage = new QWidget(this); QVBoxLayout *exvbox = new QVBoxLayout(); metaDExTab = new MetaDExDialog(); @@ -119,6 +120,7 @@ WalletView::WalletView(QWidget *parent): exTabHolder->addTab(cancelTab,tr("Cancel Orders")); exvbox->addWidget(exTabHolder); exchangePage->setLayout(exvbox); + */ // smart property page /*smartPropertyPage = new QWidget(this); @@ -151,7 +153,7 @@ WalletView::WalletView(QWidget *parent): addWidget(transactionsPage); addWidget(receiveCoinsPage); addWidget(sendCoinsPage); - addWidget(exchangePage); + //addWidget(exchangePage); //addWidget(smartPropertyPage); addWidget(toolboxPage); @@ -210,10 +212,10 @@ void WalletView::setWalletModel(WalletModel *walletModel) sendCoinsTab->setModel(walletModel); sendMPTab->setModel(walletModel); balancesView->setModel(walletModel); - metaDExTab->setModel(walletModel); +// metaDExTab->setModel(walletModel); mpTXTab->setModel(walletModel); - cancelTab->setModel(walletModel); - orderHistoryTab->setModel(walletModel); +// cancelTab->setModel(walletModel); +// orderHistoryTab->setModel(walletModel); if (walletModel) { diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 140d57d4bba5a..9608e91b63444 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -17,8 +17,8 @@ class OrderHistoryDialog; class LookupSPDialog; class LookupTXDialog; class LookupAddressDialog; -class MetaDExDialog; -class MetaDExCancelDialog; +//class MetaDExDialog; +//class MetaDExCancelDialog; class SendCoinsRecipient; class TransactionView; class TXHistoryDialog; @@ -79,8 +79,8 @@ class WalletView : public QStackedWidget LookupTXDialog *txLookupTab; LookupAddressDialog *addressLookupTab; OrderHistoryDialog *orderHistoryTab; - MetaDExDialog *metaDExTab; - MetaDExCancelDialog *cancelTab; +// MetaDExDialog *metaDExTab; +// MetaDExCancelDialog *cancelTab; TransactionView *transactionView; BalancesView *balancesView; TXHistoryDialog *mpTXTab; From b82f64537c3ead438eaacd0906afd2f3004112ef Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 16:53:09 -0800 Subject: [PATCH 098/141] Add getMySTOReceipts function --- src/mastercore.cpp | 29 +++++++++++++++++++++++++++++ src/mastercore.h | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 2b9ccecaf2f7b..415d72eb7c9dd 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3521,6 +3521,35 @@ unsigned int n_found = 0; } // MPSTOList here +std::string CMPSTOList::getMySTOReceipts() +{ + if (!sdb) return ""; + string mySTOReceipts = ""; + + Slice skey, svalue; + readoptions.fill_cache = false; + Iterator* it = sdb->NewIterator(readoptions); + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + string recipientAddress = skey.ToString(); + if(!IsMyAddress(recipientAddress)) continue; // not ours, not interested + // ours, get info + svalue = it->value(); + string strValue = svalue.ToString(); + // break into individual receipts + std::vector vstr; + boost::split(vstr, strValue, boost::is_any_of(","), token_compress_on); + for(uint32_t i = 0; i Date: Mon, 8 Dec 2014 16:57:45 -0800 Subject: [PATCH 099/141] Fix missing token --- src/mastercore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 415d72eb7c9dd..6ee22f1b1515a 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3543,7 +3543,7 @@ std::string CMPSTOList::getMySTOReceipts() for(uint32_t i = 0; i Date: Mon, 8 Dec 2014 16:58:02 -0800 Subject: [PATCH 100/141] Activate getMySTOReciepts for testing --- src/mastercore_rpc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index b941f733c1154..035db6d19c88d 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1828,6 +1828,10 @@ Value listtransactions_MP(const Array& params, bool fHelp) Array response; //prep an array to hold our output + // STO has no inbound transaction, so we need to use an insert methodology here + // get STO receipts affecting me + string mySTOReceipts = s_stolistdb->getMySTOReceipts(); + printf("%s\n",mySTOReceipts.c_str()); // rewrite to use original listtransactions methodology from core LOCK(wallet->cs_wallet); std::list acentries; From 092e570852809e08d42ad783167e012c66f4308d Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 17:24:51 -0800 Subject: [PATCH 101/141] Change model for getMySTOReceipts --- src/mastercore.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 6ee22f1b1515a..f4def6064317e 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3543,8 +3543,13 @@ std::string CMPSTOList::getMySTOReceipts() for(uint32_t i = 0; i svstr; + boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); + if(4 == svstr.size()) + { + size_t txidMatch = strValue.find(svstr[0]); + if(txidMatch!=std::string::npos) mySTOReceipts += svstr[0] + ":" + svstr[1] + ","; + } } } return mySTOReceipts; From e3e26241fef668d060e260df5beb020104a4db04 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 17:32:12 -0800 Subject: [PATCH 102/141] support filtering for example from listtransactions_MP --- src/mastercore.cpp | 3 ++- src/mastercore.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index f4def6064317e..4b539bf305ec9 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3521,7 +3521,7 @@ unsigned int n_found = 0; } // MPSTOList here -std::string CMPSTOList::getMySTOReceipts() +std::string CMPSTOList::getMySTOReceipts(string filterAddress) { if (!sdb) return ""; string mySTOReceipts = ""; @@ -3534,6 +3534,7 @@ std::string CMPSTOList::getMySTOReceipts() skey = it->key(); string recipientAddress = skey.ToString(); if(!IsMyAddress(recipientAddress)) continue; // not ours, not interested + if((!filterAddress.empty()) && (filterAddress != recipientAddress)) continue; // not the filtered address // ours, get info svalue = it->value(); string strValue = svalue.ToString(); diff --git a/src/mastercore.h b/src/mastercore.h index b30a0a0c467a4..3d750d4b02796 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -346,7 +346,7 @@ class CMPSTOList delete sdb; sdb = NULL; } - std::string getMySTOReceipts(); + std::string getMySTOReceipts(string filterAddress); void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible); int deleteAboveBlock(int blockNum); bool exists(string address); From 4ee090fd90275962a2c33c21827c26158a9534f9 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 17:53:28 -0800 Subject: [PATCH 103/141] Add divisibility to getMySTOReceipts --- src/mastercore.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 4b539bf305ec9..a7fedf7ebe8ee 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3548,8 +3548,17 @@ std::string CMPSTOList::getMySTOReceipts(string filterAddress) boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); if(4 == svstr.size()) { + uint64_t propertyId = 0; + try { + propertyId = boost::lexical_cast(svstr[2]); + } catch (const boost::bad_lexical_cast &e) { + file_log("DEBUG STO - error in converting values from leveldb\n"); + return ""; //(something went wrong) + } + string divisStr = "false"; + if (isPropertyDivisible(propertyId)) divisStr = "true"; size_t txidMatch = strValue.find(svstr[0]); - if(txidMatch!=std::string::npos) mySTOReceipts += svstr[0] + ":" + svstr[1] + ","; + if(txidMatch!=std::string::npos) mySTOReceipts += svstr[0] + ":" + svstr[1] + ":" + divisStr + ","; } } } From d857b0dfcb96589b516e23e6db02ead14ea21278 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 17:53:43 -0800 Subject: [PATCH 104/141] RPC support for STO in listtransactions_MP --- src/mastercore_rpc.cpp | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 035db6d19c88d..11971c590c769 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1830,8 +1830,12 @@ Value listtransactions_MP(const Array& params, bool fHelp) // STO has no inbound transaction, so we need to use an insert methodology here // get STO receipts affecting me - string mySTOReceipts = s_stolistdb->getMySTOReceipts(); + string mySTOReceipts = s_stolistdb->getMySTOReceipts(addressParam); printf("%s\n",mySTOReceipts.c_str()); + std::vector vecReceipts; + boost::split(vecReceipts, mySTOReceipts, boost::is_any_of(","), token_compress_on); + int64_t lastTXBlock = 999999; + // rewrite to use original listtransactions methodology from core LOCK(wallet->cs_wallet); std::list acentries; @@ -1851,6 +1855,36 @@ Value listtransactions_MP(const Array& params, bool fHelp) int blockHeight = pBlockIndex->nHeight; if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range + // look for an STO receipt to see if we need to insert it + for(uint32_t i = 0; i svstr; + boost::split(svstr, vecReceipts[i], boost::is_any_of(":"), token_compress_on); + if(3 == svstr.size()) // make sure expected num items + { + if((atoi(svstr[1]) < lastTXBlock) && (atoi(svstr[1]) > blockHeight)) + { + // STO receipt insert here - add STO receipt to response array + uint256 hash; + hash.SetHex(svstr[0]); + Object txobj; + bool divisible = false; + if (svstr[2]=="true") divisible = true; + int populateResult = -1; + populateResult = populateRPCTransactionObject(hash, &txobj); + if (0 == populateResult) + { + Array receiveArray; + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible); // get matching receipts + txobj.push_back(Pair("recipients", receiveArray)); + response.push_back(txobj); // add the transaction object to the response array + } + // don't burn time doing more work than we need to + if ((int)response.size() >= (nCount+nFrom)) break; + } + } + } + // populateRPCTransactionObject will throw us a non-0 rc if this isn't a MP transaction, speeds up search by orders of magnitude uint256 hash = pwtx->GetHash(); Object txobj; @@ -1866,6 +1900,7 @@ Value listtransactions_MP(const Array& params, bool fHelp) populateResult = populateRPCTransactionObject(hash, &txobj); // no address filter } if (0 == populateResult) response.push_back(txobj); // add the transaction object to the response array if we get a 0 rc + lastTXBlock = blockHeight; // don't burn time doing more work than we need to if ((int)response.size() >= (nCount+nFrom)) break; From 8750756967fc08a32975e5261960c492156766c6 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 17:58:46 -0800 Subject: [PATCH 105/141] Fix crash on exit --- src/mastercore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index a7fedf7ebe8ee..c11661245a3b3 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3562,6 +3562,7 @@ std::string CMPSTOList::getMySTOReceipts(string filterAddress) } } } + delete it; return mySTOReceipts; } From 31e7ee55e6a6b8284b16042ded129577ca23c8f8 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 20:40:00 -0800 Subject: [PATCH 106/141] Add total to getReceipts --- src/mastercore.cpp | 3 ++- src/mastercore.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index c11661245a3b3..fa18c12d4037a 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3566,7 +3566,7 @@ std::string CMPSTOList::getMySTOReceipts(string filterAddress) return mySTOReceipts; } -void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible) +void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible, uint64_t *total) { if (!sdb) return; @@ -3629,6 +3629,7 @@ void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array * { recipient.push_back(Pair("amount", FormatIndivisibleMP(amount))); } + total += amount; recipientArray->push_back(recipient); ++count; } diff --git a/src/mastercore.h b/src/mastercore.h index 3d750d4b02796..921a83a628033 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -347,7 +347,7 @@ class CMPSTOList sdb = NULL; } std::string getMySTOReceipts(string filterAddress); - void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible); + void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible, uint64_t *total); int deleteAboveBlock(int blockNum); bool exists(string address); void printStats(); From aef0c2aab74f4ef70cade5477bd9261fdfb9f897 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 20:55:32 -0800 Subject: [PATCH 107/141] Update method --- src/mastercore.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index fa18c12d4037a..d1c8a275da335 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3548,17 +3548,8 @@ std::string CMPSTOList::getMySTOReceipts(string filterAddress) boost::split(svstr, vstr[i], boost::is_any_of(":"), token_compress_on); if(4 == svstr.size()) { - uint64_t propertyId = 0; - try { - propertyId = boost::lexical_cast(svstr[2]); - } catch (const boost::bad_lexical_cast &e) { - file_log("DEBUG STO - error in converting values from leveldb\n"); - return ""; //(something went wrong) - } - string divisStr = "false"; - if (isPropertyDivisible(propertyId)) divisStr = "true"; size_t txidMatch = strValue.find(svstr[0]); - if(txidMatch!=std::string::npos) mySTOReceipts += svstr[0] + ":" + svstr[1] + ":" + divisStr + ","; + if(txidMatch!=std::string::npos) mySTOReceipts += svstr[0]+":"+svstr[1]+":"+recipientAddress+":"+svstr[2]+","; } } } From 8022e49adad2da5862740e7f88232e9e51db953d Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 20:55:49 -0800 Subject: [PATCH 108/141] Fix up listtransactions_MP support, appears working well now --- src/mastercore_rpc.cpp | 19 +++++--- src/qt/txhistorydialog.cpp | 95 +++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 11971c590c769..8d56cb0d1a64f 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1831,7 +1831,6 @@ Value listtransactions_MP(const Array& params, bool fHelp) // STO has no inbound transaction, so we need to use an insert methodology here // get STO receipts affecting me string mySTOReceipts = s_stolistdb->getMySTOReceipts(addressParam); - printf("%s\n",mySTOReceipts.c_str()); std::vector vecReceipts; boost::split(vecReceipts, mySTOReceipts, boost::is_any_of(","), token_compress_on); int64_t lastTXBlock = 999999; @@ -1860,7 +1859,7 @@ Value listtransactions_MP(const Array& params, bool fHelp) { std::vector svstr; boost::split(svstr, vecReceipts[i], boost::is_any_of(":"), token_compress_on); - if(3 == svstr.size()) // make sure expected num items + if(4 == svstr.size()) // make sure expected num items { if((atoi(svstr[1]) < lastTXBlock) && (atoi(svstr[1]) > blockHeight)) { @@ -1868,14 +1867,21 @@ Value listtransactions_MP(const Array& params, bool fHelp) uint256 hash; hash.SetHex(svstr[0]); Object txobj; - bool divisible = false; - if (svstr[2]=="true") divisible = true; + uint64_t propertyId = 0; + try { + propertyId = boost::lexical_cast(svstr[3]); + } catch (const boost::bad_lexical_cast &e) { + file_log("DEBUG STO - error in converting values from leveldb\n"); + continue; //(something went wrong) + } + bool divisible = isPropertyDivisible(propertyId); int populateResult = -1; populateResult = populateRPCTransactionObject(hash, &txobj); if (0 == populateResult) { Array receiveArray; - s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible); // get matching receipts + uint64_t tmpAmount = 0; + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible, &tmpAmount); // get matching receipts txobj.push_back(Pair("recipients", receiveArray)); response.push_back(txobj); // add the transaction object to the response array } @@ -2068,7 +2074,8 @@ Value getsto_MP(const Array& params, bool fHelp) } // create array of recipients Array receiveArray; - s_stolistdb->getRecipients(hash, filterAddress, &receiveArray, divisible); + uint64_t tmpAmount = 0; + s_stolistdb->getRecipients(hash, filterAddress, &receiveArray, divisible, &tmpAmount); // add matches array to object txobj.push_back(Pair("recipients", receiveArray)); } diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index c56f9ec414562..64fc02003d452 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -201,12 +201,19 @@ void TXHistoryDialog::UpdateHistory() string sAddress = ""; string addressParam = ""; - int64_t nCount = 50; //don't display more than 50 historical transactions at the moment until we can move to a cached model + int64_t nCount = 100; //don't display more than 100 historical transactions at the moment until we can move to a cached model int64_t nStartBlock = 0; int64_t nEndBlock = 999999; Array response; //prep an array to hold our output + // STO has no inbound transaction, so we need to use an insert methodology here + // get STO receipts affecting me + string mySTOReceipts = s_stolistdb->getMySTOReceipts(addressParam); + std::vector vecReceipts; + boost::split(vecReceipts, mySTOReceipts, boost::is_any_of(","), token_compress_on); + int64_t lastTXBlock = 999999; + // rewrite to use original listtransactions methodology from core LOCK(wallet->cs_wallet); std::list acentries; @@ -231,7 +238,91 @@ void TXHistoryDialog::UpdateHistory() if (NULL == pBlockIndex) continue; int blockHeight = pBlockIndex->nHeight; if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range - // check if the transaction exists in txlist, and if so is it correct type (21) + + // look for an STO receipt to see if we need to insert it + for(uint32_t i = 0; i svstr; + boost::split(svstr, vecReceipts[i], boost::is_any_of(":"), token_compress_on); + if(4 == svstr.size()) // make sure expected num items + { + if((atoi(svstr[1]) < lastTXBlock) && (atoi(svstr[1]) > blockHeight)) + { + // STO receipt insert here - add STO receipt to response array + uint256 hash; + hash.SetHex(svstr[0]); + string displayAddress = svstr[2]; + Object txobj; + uint64_t propertyId = 0; + try { + propertyId = boost::lexical_cast(svstr[3]); + } catch (const boost::bad_lexical_cast &e) { + file_log("DEBUG STO - error in converting values from leveldb\n"); + continue; //(something went wrong) + } + bool divisible = isPropertyDivisible(propertyId); + QDateTime txTime; + CBlockIndex* pBlkIdx = chainActive[atoi(svstr[1])]; + txTime.setTime_t(pBlkIdx->GetBlockTime()); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + Array receiveArray; + uint64_t total = 0; + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible, &total); // get matching receipts + QIcon ic = QIcon(":/icons/transaction_0"); + int confirmations = 1 + GetHeight() - pBlkIdx->nHeight; + switch(confirmations) + { + case 1: ic = QIcon(":/icons/transaction_1"); break; + case 2: ic = QIcon(":/icons/transaction_2"); break; + case 3: ic = QIcon(":/icons/transaction_3"); break; + case 4: ic = QIcon(":/icons/transaction_4"); break; + case 5: ic = QIcon(":/icons/transaction_5"); break; + } + if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); + string displayAmount; + string displayToken; + if (divisible) { displayAmount = FormatDivisibleShortMP(total); } else { displayAmount = FormatIndivisibleMP(total); } + if (propertyId < 3) { + if(propertyId == 1) { displayToken = " MSC"; } else { displayToken = " TMSC"; } + } else { + string s = to_string(propertyId); + displayToken = " SPT#" + s; + } + + // add to history + ui->txHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); + QTableWidgetItem *typeCell = new QTableWidgetItem("STO Receive"); + QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); + QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); + iconCell->setIcon(ic); + addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); + addressCell->setForeground(QColor("#707070")); + amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountCell->setForeground(QColor("#00AA00")); + if (rowcount % 2) + { + amountCell->setBackground(QColor("#F0F0F0")); + addressCell->setBackground(QColor("#F0F0F0")); + dateCell->setBackground(QColor("#F0F0F0")); + typeCell->setBackground(QColor("#F0F0F0")); + txidCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); + } + ui->txHistoryTable->setItem(rowcount, 0, iconCell); + ui->txHistoryTable->setItem(rowcount, 1, dateCell); + ui->txHistoryTable->setItem(rowcount, 2, typeCell); + ui->txHistoryTable->setItem(rowcount, 3, addressCell); + ui->txHistoryTable->setItem(rowcount, 4, amountCell); + ui->txHistoryTable->setItem(rowcount, 5, txidCell); + rowcount += 1; + } + } + } + lastTXBlock = blockHeight; + // check if the transaction exists in txlist if (p_txlistdb->exists(hash)) { string statusText; From 86714723beb31859b4275048ef49a4983f963806 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 21:00:23 -0800 Subject: [PATCH 109/141] minor pointer fix --- src/mastercore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index d1c8a275da335..f25f1dd20cdad 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3620,7 +3620,7 @@ void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array * { recipient.push_back(Pair("amount", FormatIndivisibleMP(amount))); } - total += amount; + *total += amount; recipientArray->push_back(recipient); ++count; } From ccf6adce8650339841c754a0c5fe98fc8b9a83c1 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 21:28:16 -0800 Subject: [PATCH 110/141] Remove requirement to supply divisibility to getReceipts --- src/mastercore.cpp | 6 ++++-- src/mastercore.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index f25f1dd20cdad..2bb6f88038281 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -3557,7 +3557,7 @@ std::string CMPSTOList::getMySTOReceipts(string filterAddress) return mySTOReceipts; } -void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible, uint64_t *total) +void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, uint64_t *total) { if (!sdb) return; @@ -3601,9 +3601,11 @@ void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array * { //add data to array uint64_t amount = 0; + uint64_t propertyId = 0; try { amount = boost::lexical_cast(svstr[3]); + propertyId = boost::lexical_cast(svstr[2]); } catch (const boost::bad_lexical_cast &e) { file_log("DEBUG STO - error in converting values from leveldb\n"); @@ -3612,7 +3614,7 @@ void CMPSTOList::getRecipients(const uint256 txid, string filterAddress, Array * } Object recipient; recipient.push_back(Pair("address", recipientAddress)); - if(divisible) + if(isPropertyDivisible(propertyId)) { recipient.push_back(Pair("amount", FormatDivisibleMP(amount))); } diff --git a/src/mastercore.h b/src/mastercore.h index 921a83a628033..d3805e626d3c4 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -347,7 +347,7 @@ class CMPSTOList sdb = NULL; } std::string getMySTOReceipts(string filterAddress); - void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, bool divisible, uint64_t *total); + void getRecipients(const uint256 txid, string filterAddress, Array *recipientArray, uint64_t *total); int deleteAboveBlock(int blockNum); bool exists(string address); void printStats(); From 47ab3779fc1d91eab3068873a43e302b4856223c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 21:28:54 -0800 Subject: [PATCH 111/141] clean up RPC --- src/mastercore_rpc.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 8d56cb0d1a64f..46d519f1e6cd9 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1867,21 +1867,13 @@ Value listtransactions_MP(const Array& params, bool fHelp) uint256 hash; hash.SetHex(svstr[0]); Object txobj; - uint64_t propertyId = 0; - try { - propertyId = boost::lexical_cast(svstr[3]); - } catch (const boost::bad_lexical_cast &e) { - file_log("DEBUG STO - error in converting values from leveldb\n"); - continue; //(something went wrong) - } - bool divisible = isPropertyDivisible(propertyId); int populateResult = -1; populateResult = populateRPCTransactionObject(hash, &txobj); if (0 == populateResult) { Array receiveArray; uint64_t tmpAmount = 0; - s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible, &tmpAmount); // get matching receipts + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &tmpAmount); // get matching receipts txobj.push_back(Pair("recipients", receiveArray)); response.push_back(txobj); // add the transaction object to the response array } @@ -2075,7 +2067,7 @@ Value getsto_MP(const Array& params, bool fHelp) // create array of recipients Array receiveArray; uint64_t tmpAmount = 0; - s_stolistdb->getRecipients(hash, filterAddress, &receiveArray, divisible, &tmpAmount); + s_stolistdb->getRecipients(hash, filterAddress, &receiveArray, &tmpAmount); // add matches array to object txobj.push_back(Pair("recipients", receiveArray)); } From 80baf1acedd55338caa8a0e72dea0b23831d06b1 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Mon, 8 Dec 2014 21:29:04 -0800 Subject: [PATCH 112/141] Changes to TX History form to accomodate STO --- src/qt/txhistorydialog.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 64fc02003d452..2cb297425a32f 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -267,7 +267,7 @@ void TXHistoryDialog::UpdateHistory() QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); Array receiveArray; uint64_t total = 0; - s_stolistdb->getRecipients(hash, addressParam, &receiveArray, divisible, &total); // get matching receipts + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &total); // get matching receipts QIcon ic = QIcon(":/icons/transaction_0"); int confirmations = 1 + GetHeight() - pBlkIdx->nHeight; switch(confirmations) @@ -508,6 +508,16 @@ void TXHistoryDialog::showDetails() if (0<=pop) { strTXText = write_string(Value(txobj), false) + "\n"; + // manipulate for STO if needed + size_t pos = strTXText.find("Send To Owners"); + if (pos!=std::string::npos) { + Array receiveArray; + uint64_t tmpAmount = 0; + s_stolistdb->getRecipients(txid, "", &receiveArray, &tmpAmount); + txobj.push_back(Pair("recipients", receiveArray)); + //rewrite string + strTXText = write_string(Value(txobj), false) + "\n"; + } } } @@ -546,7 +556,14 @@ void TXHistoryDialog::showDetails() strTXText.replace(start_pos, from.length(), to); start_pos += to.length(); // Handles case where 'to' is a substring of 'from' } - + from = "["; + to = "[\n"; + start_pos = 0; + while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) + { + strTXText.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } QString txText = QString::fromStdString(strTXText); QDialog *txDlg = new QDialog; QLayout *dlgLayout = new QVBoxLayout; From 905f78305c1a0b55723277316be84b5d9e0bc266 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 11 Dec 2014 14:00:30 -0800 Subject: [PATCH 113/141] Increase initial window size --- src/qt/bitcoingui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b156dd47bfb63..70c6078e46ed8 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -70,7 +70,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : prevBlocks(0), spinnerFrame(0) { - GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this); + GUIUtil::restoreWindowGeometry("nWindow", QSize(680, 650), this); QString windowTitle = tr("Master Core") + " - "; #ifdef ENABLE_WALLET From 22a1d65620a6e2aecad6df3198ca41290e1e73be Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 11 Dec 2014 20:04:34 -0800 Subject: [PATCH 114/141] Remove metadex files not used in this UI build --- src/qt/metadexcanceldialog.cpp | 176 ------- src/qt/metadexcanceldialog.h | 54 --- src/qt/metadexdialog.cpp | 807 --------------------------------- src/qt/metadexdialog.h | 70 --- src/qt/orderhistorydialog.cpp | 622 ------------------------- src/qt/orderhistorydialog.h | 73 --- 6 files changed, 1802 deletions(-) delete mode 100644 src/qt/metadexcanceldialog.cpp delete mode 100644 src/qt/metadexcanceldialog.h delete mode 100644 src/qt/metadexdialog.cpp delete mode 100644 src/qt/metadexdialog.h delete mode 100644 src/qt/orderhistorydialog.cpp delete mode 100644 src/qt/orderhistorydialog.h diff --git a/src/qt/metadexcanceldialog.cpp b/src/qt/metadexcanceldialog.cpp deleted file mode 100644 index dea45e51e8cc9..0000000000000 --- a/src/qt/metadexcanceldialog.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) 2011-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "metadexcanceldialog.h" -#include "ui_metadexcanceldialog.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "coincontroldialog.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "walletmodel.h" -#include "wallet.h" -#include "base58.h" -#include "coincontrol.h" -#include "ui_interface.h" - -#include - -#include "leveldb/db.h" -#include "leveldb/write_batch.h" - -// potentially overzealous includes here -#include "base58.h" -#include "rpcserver.h" -#include "init.h" -#include "util.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" -#include "leveldb/db.h" -#include "leveldb/write_batch.h" -// end potentially overzealous includes -using namespace json_spirit; // since now using Array in mastercore.h this needs to come first - -#include "mastercore.h" -using namespace mastercore; - -// potentially overzealous using here -using namespace std; -using namespace boost; -using namespace boost::assign; -using namespace leveldb; -// end potentially overzealous using - -#include "mastercore_dex.h" -#include "mastercore_parse_string.h" -#include "mastercore_tx.h" -#include "mastercore_sp.h" - -#include -#include -#include -#include - -MetaDExCancelDialog::MetaDExCancelDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::MetaDExCancelDialog), - model(0) -{ - ui->setupUi(this); - - connect(ui->radioCancelPair, SIGNAL(clicked()),this, SLOT(rdoCancelPair())); - connect(ui->radioCancelPrice, SIGNAL(clicked()),this, SLOT(rdoCancelPrice())); - connect(ui->radioCancelEverything, SIGNAL(clicked()),this, SLOT(rdoCancelEverything())); - -} -void MetaDExCancelDialog::rdoCancelPair() -{ - // calculate which pairs are currently open - ui->cancelCombo->clear(); - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - md_Set & indexes = (it->second); - // loop through each entry and sum up any sells for the right pair - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if(IsMyAddress(obj.getAddr())) - { - string comboStr; - string sellToken; - string desiredToken; - // work out pair name - sellToken = getPropertyName(obj.getProperty()).c_str(); - if(sellToken.size()>30) sellToken=sellToken.substr(0,30)+"..."; - string sellId = static_cast( &(ostringstream() << obj.getProperty()) )->str(); - sellToken += " (#" + sellId + ")"; - desiredToken = getPropertyName(obj.getDesProperty()).c_str(); - if(desiredToken.size()>30) desiredToken=desiredToken.substr(0,30)+"..."; - string desiredId = static_cast( &(ostringstream() << obj.getDesProperty()) )->str(); - desiredToken += " (#" + desiredId + ")"; - comboStr = "Cancel all orders selling " + sellToken + " for " + desiredToken; - //only add if not already there - int index = ui->cancelCombo->findText(QString::fromStdString(comboStr)); - if ( index == -1 ) { ui->cancelCombo->addItem(QString::fromStdString(comboStr),QString::fromStdString(sellId+"/"+desiredId)); } - } - } - } - } -} - -void MetaDExCancelDialog::rdoCancelPrice() -{ - // calculate which pairs are currently open and their prices - ui->cancelCombo->clear(); - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - XDOUBLE price = (1/it->first); - string priceStr = price.str(15, std::ios_base::fixed); - md_Set & indexes = (it->second); - // loop through each entry and sum up any sells for the right pair - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if(IsMyAddress(obj.getAddr())) - { - string comboStr; - string sellToken; - string desiredToken; - // work out pair name - sellToken = getPropertyName(obj.getProperty()).c_str(); - if(sellToken.size()>30) sellToken=sellToken.substr(0,30)+"..."; - string sellId = static_cast( &(ostringstream() << obj.getProperty()) )->str(); - sellToken += " (#" + sellId + ")"; - desiredToken = getPropertyName(obj.getDesProperty()).c_str(); - if(desiredToken.size()>30) desiredToken=desiredToken.substr(0,30)+"..."; - string desiredId = static_cast( &(ostringstream() << obj.getDesProperty()) )->str(); - desiredToken += " (#" + desiredId + ")"; - comboStr = "Cancel all orders priced at " + priceStr + " selling " + sellToken + " for " + desiredToken; - //only add if not already there - int index = ui->cancelCombo->findText(QString::fromStdString(comboStr)); - if ( index == -1 ) { ui->cancelCombo->addItem(QString::fromStdString(comboStr),QString::fromStdString(sellId+"/"+desiredId)); } - } - } - } - } - -} - -void MetaDExCancelDialog::rdoCancelEverything() -{ - // only one option here - ui->cancelCombo->clear(); - ui->cancelCombo->addItem("All currently active sell orders","ALL"); //use last possible ID for summary for now -} - -void MetaDExCancelDialog::setModel(WalletModel *model) -{ - this->model = model; -// connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(balancesUpdated())); -} - -void MetaDExCancelDialog::sendCancelTransaction() -{ - -} - diff --git a/src/qt/metadexcanceldialog.h b/src/qt/metadexcanceldialog.h deleted file mode 100644 index 5a29229e951b8..0000000000000 --- a/src/qt/metadexcanceldialog.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef METADEXCANCELDIALOG_H -#define METADEXCANCELDIALOG_H - -#include "walletmodel.h" - -#include -#include - -class OptionsModel; - -QT_BEGIN_NAMESPACE -class QUrl; -QT_END_NAMESPACE - -namespace Ui { - class MetaDExCancelDialog; -} - -/** Dialog for sending Master Protocol tokens */ -class MetaDExCancelDialog : public QDialog -{ - Q_OBJECT - -public: - explicit MetaDExCancelDialog(QWidget *parent = 0); - - void setModel(WalletModel *model); - void sendCancelTransaction(); - /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). - */ - QWidget *setupTabChain(QWidget *prev); - - -public slots: - void rdoCancelPair(); - void rdoCancelPrice(); - void rdoCancelEverything(); - -private: - Ui::MetaDExCancelDialog *ui; - WalletModel *model; - -private slots: - -signals: - // Fired when a message should be reported to the user - void message(const QString &title, const QString &message, unsigned int style); -}; - -#endif // METADEXCANCELDIALOG_H diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp deleted file mode 100644 index bb10fa0338e97..0000000000000 --- a/src/qt/metadexdialog.cpp +++ /dev/null @@ -1,807 +0,0 @@ -// Copyright (c) 2011-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "metadexdialog.h" -#include "ui_metadexdialog.h" - -#include "guiutil.h" -#include "optionsmodel.h" -#include "walletmodel.h" -#include "wallet.h" -#include "base58.h" -#include "ui_interface.h" - -#include - -#include "leveldb/db.h" -#include "leveldb/write_batch.h" - -// potentially overzealous includes here -#include "base58.h" -#include "rpcserver.h" -#include "init.h" -#include "util.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" -#include "leveldb/db.h" -#include "leveldb/write_batch.h" -// end potentially overzealous includes - -using namespace json_spirit; -#include "mastercore.h" -using namespace mastercore; - -// potentially overzealous using here -using namespace std; -using namespace boost; -using namespace boost::assign; -using namespace leveldb; -// end potentially overzealous using - -#include "mastercore_dex.h" -#include "mastercore_tx.h" -#include "mastercore_sp.h" -#include "mastercore_parse_string.h" - -#include -#include -#include - -using boost::multiprecision::int128_t; -using boost::multiprecision::cpp_int; -using boost::multiprecision::cpp_dec_float; -using boost::multiprecision::cpp_dec_float_100; - -#include -#include -#include -#include - -MetaDExDialog::MetaDExDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::MetaDExDialog), - model(0) -{ - ui->setupUi(this); - this->model = model; - //open - global_metadex_market = 3; - - //hide pending -// ui->pendingLabel->setVisible(false); - //prep lists - ui->buyList->setColumnCount(3); - ui->sellList->setColumnCount(3); -// ui->openOrders->setColumnCount(5); - - //dummy orders -// const int currentRow = ui->openOrders->rowCount(); -// ui->openOrders->setRowCount(currentRow + 1); -// ui->openOrders->setItem(currentRow, 0, new QTableWidgetItem("1FakeBitcoinAddressDoNotSend")); -// ui->openOrders->setItem(currentRow, 1, new QTableWidgetItem("Sell")); -// ui->openOrders->setItem(currentRow, 2, new QTableWidgetItem("0.00004565")); -// ui->openOrders->setItem(currentRow, 3, new QTableWidgetItem("345.45643222")); -// ui->openOrders->setItem(currentRow, 4, new QTableWidgetItem("0.015770081")); - -// ui->openOrders->setHorizontalHeaderItem(0, new QTableWidgetItem("Address")); -// ui->openOrders->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); -// ui->openOrders->setHorizontalHeaderItem(2, new QTableWidgetItem("Unit Price")); -// ui->openOrders->verticalHeader()->setVisible(false); - #if QT_VERSION < 0x050000 -// ui->openOrders->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); - #else -// ui->openOrders->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - #endif -// ui->openOrders->horizontalHeader()->resizeSection(1, 60); -// ui->openOrders->horizontalHeader()->resizeSection(2, 140); -// ui->openOrders->horizontalHeader()->resizeSection(3, 140); -// ui->openOrders->horizontalHeader()->resizeSection(4, 140); -// ui->openOrders->setShowGrid(false); -// ui->openOrders->setSelectionBehavior(QAbstractItemView::SelectRows); - - ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); - ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); - ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); - ui->buyList->verticalHeader()->setVisible(false); - ui->buyList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); - ui->buyList->setShowGrid(false); - ui->buyList->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->buyList->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->buyList->setSelectionMode(QAbstractItemView::SingleSelection); - - ui->sellList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); - ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#3")); - ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); - ui->sellList->verticalHeader()->setVisible(false); - ui->sellList->horizontalHeader()->setResizeMode(QHeaderView::Stretch); - ui->sellList->setShowGrid(false); - ui->sellList->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->sellList->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->sellList->setSelectionMode(QAbstractItemView::SingleSelection); - - ui->pendingLabel->setVisible(false); - - connect(ui->switchButton, SIGNAL(clicked()), this, SLOT(switchButtonClicked())); - connect(ui->buyButton, SIGNAL(clicked()), this, SLOT(buyTrade())); - connect(ui->sellButton, SIGNAL(clicked()), this, SLOT(sellTrade())); - connect(ui->sellAddressCombo, SIGNAL(activated(int)), this, SLOT(sellAddressComboBoxChanged(int))); - connect(ui->buyAddressCombo, SIGNAL(activated(int)), this, SLOT(buyAddressComboBoxChanged(int))); - connect(ui->sellAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); - connect(ui->sellPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(sellRecalc())); - connect(ui->buyAmountLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); - connect(ui->buyPriceLE, SIGNAL(textEdited(const QString &)), this, SLOT(buyRecalc())); - connect(ui->sellList, SIGNAL(cellClicked(int,int)), this, SLOT(sellClicked(int,int))); - connect(ui->buyList, SIGNAL(cellClicked(int,int)), this, SLOT(buyClicked(int,int))); - - FullRefresh(); - -} - -void MetaDExDialog::setModel(WalletModel *model) -{ - this->model = model; - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh())); -} - -void MetaDExDialog::OrderRefresh() -{ - UpdateSellOffers(); - UpdateBuyOffers(); - // check for pending transactions, could be more filtered to just trades here - bool pending = false; - for(PendingMap::iterator my_it = my_pending.begin(); my_it != my_pending.end(); ++my_it) - { - // if we get here there are pending transactions in the wallet, flag warning to MetaDEx - pending = true; - } - if(pending) { ui->pendingLabel->setVisible(true); } else { ui->pendingLabel->setVisible(false); } -} - -void MetaDExDialog::SwitchMarket() -{ - uint64_t searchPropertyId = 0; - // first let's check if we have a searchText, if not do nothing - string searchText = ui->switchLineEdit->text().toStdString(); - if (searchText.empty()) return; - - // try seeing if we have a numerical search string, if so treat it as a property ID search - try - { - searchPropertyId = boost::lexical_cast(searchText); - } - catch(const boost::bad_lexical_cast &e) { return; } // bad cast to number - - if ((searchPropertyId > 0) && (searchPropertyId < 4294967290)) // sanity check - { - // check if trying to trade against self - if ((searchPropertyId == 1) || (searchPropertyId == 2)) - { - //todo add property cannot be traded against self messgevox - return; - } - // check if property exists - bool spExists = _my_sps->hasSP(searchPropertyId); - if (!spExists) - { - //todo add property not found messagebox - return; - } - else - { - global_metadex_market = searchPropertyId; - FullRefresh(); - } - } - OrderRefresh(); -} - - -void MetaDExDialog::buyClicked(int row, int col) -{ -printf("clickedbuyoffer\n"); -} - -void MetaDExDialog::sellClicked(int row, int col) -{ -printf("clickedselloffer\n"); -} - -void MetaDExDialog::UpdateSellOffers() -{ - ui->sellList->clear(); - int rowcount = 0; - bool testeco = isTestEcosystemProperty(global_metadex_market); - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - // look for the property - if (my_it->first != global_metadex_market) { continue; } - - // loop prices and list any sells for the right pair - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - //XDOUBLE price = (it->first); - int64_t available = 0; - int64_t total = 0; - bool includesMe = false; - md_Set & indexes = (it->second); - // loop through each entry and sum up any sells for the right pair - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if ( ((testeco) && (obj.getDesProperty() == 2)) || ((!testeco) && (obj.getDesProperty() == 1)) ) - { - available += obj.getAmountForSale(); - total += obj.getAmountDesired(); - if(IsMyAddress(obj.getAddr())) includesMe = true; - } - } - // done checking this price, if there are any available/total add to pricebook - if ((available > 0) && (total > 0)) - { - // add to pricebook - double price = (double)total/(double)available; - QString pstr = QString::fromStdString(FormatPriceMP(price)); //(strprintf("%20.10lf",price));//FormatDivisibleAmount(price)); - QString tstr = QString::fromStdString(FormatDivisibleShortMP(available)); - QString mstr = QString::fromStdString(FormatDivisibleShortMP(total)); - if (!ui->sellList) { printf("metadex dialog error\n"); return; } - ui->sellList->setRowCount(rowcount+2); - ui->sellList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); - ui->sellList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); - ui->sellList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); - ui->sellList->item(rowcount, 0)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - ui->sellList->item(rowcount, 1)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - ui->sellList->item(rowcount, 2)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - - if(includesMe) - { - QFont font; - font.setBold(true); - ui->sellList->item(rowcount, 0)->setFont(font); - ui->sellList->item(rowcount, 1)->setFont(font); - ui->sellList->item(rowcount, 2)->setFont(font); - } - rowcount += 1; - } - } - } - ui->sellList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); - ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#" + QString::fromStdString(FormatIndivisibleMP(global_metadex_market)))); - if (!testeco) { ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); } else { ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total TMSC")); } -} - -void MetaDExDialog::UpdateBuyOffers() -{ - ui->buyList->clear(); - int rowcount = 0; - bool testeco = isTestEcosystemProperty(global_metadex_market); - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - // look for the property - unsigned int mapPropertyId = my_it->first; - if ( ((testeco) && (mapPropertyId != 2)) || ((!testeco) && (mapPropertyId != 1)) ) continue; - - // loop prices and list any sells for the right pair - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - //XDOUBLE price = (1/it->first); - double available = 0; - double total = 0; - bool includesMe = false; - md_Set & indexes = (it->second); - // loop through each entry and sum up any sells for the right pair - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if(obj.getDesProperty()==global_metadex_market) - { - available += obj.getAmountDesired(); - total += obj.getAmountForSale(); - if(IsMyAddress(obj.getAddr())) includesMe = true; - } - } - // done checking this price, if there are any available/total add to pricebook - if ((available > 0) && (total > 0)) - { - // add to pricebook - double price = (double)total/(double)available; - QString pstr = QString::fromStdString(FormatPriceMP(price)); - QString tstr = QString::fromStdString(FormatDivisibleShortMP(available)); - QString mstr = QString::fromStdString(FormatDivisibleShortMP(total)); - if (!ui->buyList) { printf("metadex dialog error\n"); return; } - ui->buyList->setRowCount(rowcount+2); - ui->buyList->setItem(rowcount, 0, new QTableWidgetItem(pstr)); - ui->buyList->setItem(rowcount, 1, new QTableWidgetItem(tstr)); - ui->buyList->setItem(rowcount, 2, new QTableWidgetItem(mstr)); - ui->buyList->item(rowcount, 0)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - ui->buyList->item(rowcount, 1)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - ui->buyList->item(rowcount, 2)->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - - if(includesMe) - { - QFont font; - font.setBold(true); - ui->buyList->item(rowcount, 0)->setFont(font); - ui->buyList->item(rowcount, 1)->setFont(font); - ui->buyList->item(rowcount, 2)->setFont(font); - } - rowcount += 1; - } - } - } - ui->buyList->setHorizontalHeaderItem(0, new QTableWidgetItem("Unit Price")); - ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("Total SP#" + QString::fromStdString(FormatIndivisibleMP(global_metadex_market)))); - if (!testeco) { ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total MSC")); } else { ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("Total TMSC")); } -} - -void MetaDExDialog::UpdateSellAddress() -{ - unsigned int propertyId = global_metadex_market; - bool divisible = isPropertyDivisible(propertyId); - QString currentSetSellAddress = ui->sellAddressCombo->currentText(); - int64_t balanceAvailable = getUserAvailableMPbalance(currentSetSellAddress.toStdString(), propertyId); - string labStr; - if (divisible) - { - labStr = "Your balance: " + FormatDivisibleMP(balanceAvailable) + " SPT"; - } - else - { - labStr = "Your balance: " + FormatIndivisibleMP(balanceAvailable) + " SPT"; - } - QString qLabStr = QString::fromStdString(labStr); - ui->yourSellBalanceLabel->setText(qLabStr); -} - -void MetaDExDialog::UpdateBuyAddress() -{ - unsigned int propertyId = global_metadex_market; - bool testeco = false; - if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - QString currentSetBuyAddress = ui->buyAddressCombo->currentText(); - int64_t balanceAvailable; - string tokenStr; - if (testeco) - { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), OMNI_PROPERTY_TMSC); - tokenStr = " TMSC"; - } - else - { - balanceAvailable = getUserAvailableMPbalance(currentSetBuyAddress.toStdString(), OMNI_PROPERTY_MSC); - tokenStr = " MSC"; - - } - string labStr = "Your balance: " + FormatDivisibleMP(balanceAvailable) + tokenStr; - QString qLabStr = QString::fromStdString(labStr); - ui->yourBuyBalanceLabel->setText(qLabStr); -} - -void MetaDExDialog::FullRefresh() -{ - // populate from address selector - unsigned int propertyId = global_metadex_market; - string propNameStr = getPropertyName(propertyId); - bool testeco = false; - if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - if(testeco) - { - ui->marketLabel->setText(QString::fromStdString("Trade " + propNameStr + " (#" + FormatIndivisibleMP(propertyId) + ") for Test Mastercoin")); - } - else - { - ui->marketLabel->setText(QString::fromStdString("Trade " + propNameStr + " (#" + FormatIndivisibleMP(propertyId) + ") for Mastercoin")); - } - LOCK(cs_tally); - - // get currently selected addresses - QString currentSetBuyAddress = ui->buyAddressCombo->currentText(); - QString currentSetSellAddress = ui->sellAddressCombo->currentText(); - - // clear address selectors - ui->buyAddressCombo->clear(); - ui->sellAddressCombo->clear(); - - // update form labels - if (testeco) - { - ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/TMSC"); - ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("TMSC")); - ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("TMSC")); - ui->buyTotalLabel->setText("0.00000000 TMSC"); - ui->sellTotalLabel->setText("0.00000000 TMSC"); -// ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); -// ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("TMSC")); - ui->sellTM->setText("TMSC"); - ui->buyTM->setText("TMSC"); - } - else - { - ui->exchangeLabel->setText("Exchange - SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)) + "/MSC"); - ui->buyList->setHorizontalHeaderItem(2, new QTableWidgetItem("MSC")); - ui->sellList->setHorizontalHeaderItem(2, new QTableWidgetItem("MSC")); - ui->buyTotalLabel->setText("0.00000000 MSC"); - ui->sellTotalLabel->setText("0.00000000 MSC"); -// ui->openOrders->setHorizontalHeaderItem(3, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); -// ui->openOrders->setHorizontalHeaderItem(4, new QTableWidgetItem("MSC")); - ui->sellTM->setText("MSC"); - ui->buyTM->setText("MSC"); - } - - ui->buyMarketLabel->setText("BUY SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); - ui->sellMarketLabel->setText("SELL SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); - ui->buyList->setHorizontalHeaderItem(1, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); - ui->sellList->setHorizontalHeaderItem(1, new QTableWidgetItem("SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId)))); - ui->sellButton->setText("Sell SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); - ui->buyButton->setText("Buy SP#" + QString::fromStdString(FormatIndivisibleMP(propertyId))); - - // sell addresses - for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) - { - string address = (my_it->first).c_str(); - unsigned int id; - bool includeAddress=false; - (my_it->second).init(); - while (0 != (id = (my_it->second).next())) - { - if(id==propertyId) { includeAddress=true; break; } - } - if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId - if (!IsMyAddress(address)) continue; //ignore this address, it's not ours - ui->sellAddressCombo->addItem((my_it->first).c_str()); - } - // buy addresses - for(map::iterator my_it = mp_tally_map.begin(); my_it != mp_tally_map.end(); ++my_it) - { - string address = (my_it->first).c_str(); - unsigned int id; - bool includeAddress=false; - (my_it->second).init(); - while (0 != (id = (my_it->second).next())) - { - if((id==OMNI_PROPERTY_MSC) && (!testeco)) { includeAddress=true; break; } - if((id==OMNI_PROPERTY_TMSC) && (testeco)) { includeAddress=true; break; } - } - if (!includeAddress) continue; //ignore this address, has never transacted in this propertyId - if (!IsMyAddress(address)) continue; //ignore this address, it's not ours - ui->buyAddressCombo->addItem((my_it->first).c_str()); - } - - // attempt to set buy and sell addresses back to values before refresh - int sellIdx = ui->sellAddressCombo->findText(currentSetSellAddress); - if (sellIdx != -1) { ui->sellAddressCombo->setCurrentIndex(sellIdx); } // -1 means the new prop doesn't have the previously selected address - int buyIdx = ui->buyAddressCombo->findText(currentSetBuyAddress); - if (buyIdx != -1) { ui->buyAddressCombo->setCurrentIndex(buyIdx); } // -1 means the new prop doesn't have the previously selected address - // update the balances - UpdateSellAddress(); - UpdateBuyAddress(); - UpdateBuyOffers(); - UpdateSellOffers(); - // silly sizing -// QRect rect = ui->openOrders->geometry(); -// int tableHeight = 2 + ui->openOrders->horizontalHeader()->height(); -// for(int i = 0; i < ui->openOrders->rowCount(); i++){ -// tableHeight += ui->openOrders->rowHeight(i); -// } -// rect.setHeight(tableHeight); -// ui->openOrders->setGeometry(rect); -} - -void MetaDExDialog::buyAddressComboBoxChanged(int idx) -{ - UpdateBuyAddress(); -} - -void MetaDExDialog::sellAddressComboBoxChanged(int idx) -{ - UpdateSellAddress(); -} - -void MetaDExDialog::switchButtonClicked() -{ - SwitchMarket(); -} - -void MetaDExDialog::sellTrade() -{ - sendTrade(true); -} - -void MetaDExDialog::buyTrade() -{ - sendTrade(false); -} - - -void MetaDExDialog::buyRecalc() -{ - unsigned int propertyId = global_metadex_market; - bool divisible = isPropertyDivisible(propertyId); - bool testeco = false; - if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - uint64_t buyAmount = StrToInt64(ui->buyAmountLE->text().toStdString(),divisible); - uint64_t buyPrice = StrToInt64(ui->buyPriceLE->text().toStdString(),true); - - if ((0>=buyAmount) || (0>=buyPrice)) { ui->buyTotalLabel->setText("N/A"); return; } // break out before invalid calc - - //could result in overflow TODO - uint64_t totalPrice = 0; - if(divisible) { totalPrice = (buyAmount * buyPrice)/COIN; } else { totalPrice = buyAmount * buyPrice; } - - string totalLabel = FormatDivisibleMP(totalPrice); - if (testeco) - { - ui->buyTotalLabel->setText(QString::fromStdString(totalLabel) + " TMSC"); - } - else - { - ui->buyTotalLabel->setText(QString::fromStdString(totalLabel) + " MSC"); - } -} - -void MetaDExDialog::sellRecalc() -{ - unsigned int propertyId = global_metadex_market; - bool divisible = isPropertyDivisible(propertyId); - bool testeco = false; - if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - uint64_t sellAmount = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); - uint64_t sellPrice = StrToInt64(ui->sellPriceLE->text().toStdString(),true); - if ((0>=sellAmount) || (0>=sellPrice)) { ui->sellTotalLabel->setText("N/A"); return; } // break out before invalid calc - - //could result in overflow TODO - uint64_t totalPrice; - if(divisible) { totalPrice = (sellAmount * sellPrice)/COIN; } else { totalPrice = sellAmount * sellPrice; } - - string totalLabel = FormatDivisibleMP(totalPrice); - if (testeco) - { - ui->sellTotalLabel->setText(QString::fromStdString(totalLabel) + " TMSC"); - } - else - { - ui->sellTotalLabel->setText(QString::fromStdString(totalLabel) + " MSC"); - } -} - -void MetaDExDialog::sendTrade(bool sell) -{ - unsigned int propertyId = global_metadex_market; - bool divisible = isPropertyDivisible(propertyId); - bool testeco = false; - if (propertyId >= TEST_ECO_PROPERTY_1) testeco = true; - - // obtain the selected sender address - string strFromAddress; - if (!sell) { strFromAddress = ui->buyAddressCombo->currentText().toStdString(); } else { strFromAddress = ui->sellAddressCombo->currentText().toStdString(); } - // push recipient address into a CBitcoinAddress type and check validity - CBitcoinAddress fromAddress; - if (false == strFromAddress.empty()) { fromAddress.SetString(strFromAddress); } - if (!fromAddress.IsValid()) - { - QMessageBox::critical( this, "Unable to send MetaDEx transaction", - "The sender address selected is not valid.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); - return; - } - - // warn if we have to truncate the amount due to a decimal amount for an indivisible property, but allow send to continue - -// need to handle sell too - string strAmount = ui->buyAmountLE->text().toStdString(); - if (!divisible) - { - size_t pos = strAmount.find("."); - if (pos!=std::string::npos) - { - string tmpStrAmount = strAmount.substr(0,pos); - string strMsgText = "The amount entered contains a decimal however the property being transacted is indivisible.\n\nThe amount entered will be truncated as follows:\n"; - strMsgText += "Original amount entered: " + strAmount + "\nAmount that will be used: " + tmpStrAmount + "\n\n"; - strMsgText += "Do you still wish to proceed with the transaction?"; - QString msgText = QString::fromStdString(strMsgText); - QMessageBox::StandardButton responseClick; - responseClick = QMessageBox::question(this, "Amount truncation warning", msgText, QMessageBox::Yes|QMessageBox::No); - if (responseClick == QMessageBox::No) - { - QMessageBox::critical( this, "MetaDEx transaction cancelled", - "The MetaDEx transaction has been cancelled.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); - return; - } - strAmount = tmpStrAmount; - ui->buyAmountLE->setText(QString::fromStdString(strAmount)); - } - } - - // use strToInt64 function to get the amounts, using divisibility of the property - // make fields for trade - uint64_t amountDes; - uint64_t amountSell; - uint64_t price; - unsigned int propertyIdDes; - unsigned int propertyIdSell; - - if(sell) - { - amountSell = StrToInt64(ui->sellAmountLE->text().toStdString(),divisible); - price = StrToInt64(ui->sellPriceLE->text().toStdString(),true); - if(divisible) { amountDes = (amountSell * price)/COIN; } else { amountDes = amountSell * price; } - if(testeco) { propertyIdDes = 2; } else { propertyIdDes = 1; } - propertyIdSell = global_metadex_market; - } - else - { - amountDes = StrToInt64(ui->buyAmountLE->text().toStdString(),divisible); - price = StrToInt64(ui->buyPriceLE->text().toStdString(),true); - if(divisible) { amountSell = (amountDes * price)/COIN; } else { amountSell = amountDes * price; } - if(testeco) { propertyIdSell = 2; } else { propertyIdSell = 1; } - propertyIdDes = global_metadex_market; - } - - if ((0>=amountDes) || (0>=amountSell) || (0>=propertyIdDes) || (0>=propertyIdSell)) - { - QMessageBox::critical( this, "Unable to send MetaDEx transaction", - "The amount entered is not valid.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); - return; - } - - // check if sending address has enough funds - int64_t balanceAvailable = 0; - balanceAvailable = getUserAvailableMPbalance(fromAddress.ToString(), propertyIdSell); - if (amountSell>balanceAvailable) - { - QMessageBox::critical( this, "Unable to send MetaDEx transaction", - "The selected sending address does not have a sufficient balance to cover the amount entered.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); - return; - } - - // check if wallet is still syncing, as this will currently cause a lockup if we try to send - compare our chain to peers to see if we're up to date - // Bitcoin Core devs have removed GetNumBlocksOfPeers, switching to a time based best guess scenario - uint32_t intBlockDate = GetLatestBlockTime(); // uint32, not using time_t for portability - QDateTime currentDate = QDateTime::currentDateTime(); - int secs = QDateTime::fromTime_t(intBlockDate).secsTo(currentDate); - if(secs > 90*60) - { - QMessageBox::critical( this, "Unable to send MetaDEx transaction", - "The client is still synchronizing. Sending transactions can currently be performed only when the client has completed synchronizing." ); - return; - } - - // validation checks all look ok, let's throw up a confirmation dialog - string strMsgText = "You are about to send the following MetaDEx transaction, please check the details thoroughly:\n\n"; - string spNum = static_cast( &(ostringstream() << propertyId) )->str(); - string propDetails = "#" + spNum; - string buyStr; - string sellStr; - if (!sell) strMsgText += "Your buy will be inverted into a sell offer.\n\n"; - strMsgText += "Type: Trade Request\nFrom: " + fromAddress.ToString() + "\n\n"; - if (!sell) // clicked buy - { - if (divisible) { buyStr = FormatDivisibleMP(amountDes); } else { buyStr = FormatIndivisibleMP(amountDes); } - buyStr += " SPT " + propDetails + ""; - sellStr = FormatDivisibleMP(amountSell); - if (testeco) { sellStr += " TMSC"; } else { sellStr += " MSC"; } - strMsgText += "Buying: " + buyStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; - if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } - strMsgText += "\nTotal: " + sellStr; - } - else // clicked sell - { - buyStr = FormatDivisibleMP(amountDes); - if (divisible) { sellStr = FormatDivisibleMP(amountSell); } else { sellStr = FormatIndivisibleMP(amountSell); } - if (testeco) { buyStr += " TMSC"; } else { buyStr += " MSC"; } - sellStr += " SPT " + propDetails + ""; - strMsgText += "Selling: " + sellStr + "\nPrice: " + FormatDivisibleMP(price) + " SP" + propDetails + "/"; - if (testeco) { strMsgText += "TMSC"; } else { strMsgText += "MSC"; } - strMsgText += "\nTotal: " + buyStr; - } - - strMsgText += "\n\nAre you sure you wish to send this transaction?"; - QString msgText = QString::fromStdString(strMsgText); - QMessageBox::StandardButton responseClick; - responseClick = QMessageBox::question(this, "Confirm MetaDEx transaction", msgText, QMessageBox::Yes|QMessageBox::No); - if (responseClick == QMessageBox::No) - { - QMessageBox::critical( this, "MetaDEx transaction cancelled", - "The transaction has been cancelled.\n\nPlease double-check the transction details thoroughly before retrying your transaction." ); - return; - } - - // unlock the wallet - WalletModel::UnlockContext ctx(model->requestUnlock()); - if(!ctx.isValid()) - { - // Unlock wallet was cancelled/failed - QMessageBox::critical( this, "MetaDEx transaction failed", - "The transaction has been cancelled.\n\nThe wallet unlock process must be completed to send a transaction." ); - return; - } - - // send the transaction - UI will not send any extra reference amounts at this stage - int code = 0; -// uint256 sendTXID = send_INTERNAL_1packet(fromAddress.ToString(), refAddress.ToString(), fromAddress.ToString(), propertyId, sendAmount, 0, 0, MSC_TYPE_SIMPLE_SEND, 0, &code); - uint256 tradeTXID = send_INTERNAL_1packet(fromAddress.ToString(), "", fromAddress.ToString(), propertyIdSell, amountSell, propertyIdDes, amountDes, MSC_TYPE_METADEX, 1, &code); - - if (0 != code) - { - string strCode = boost::lexical_cast(code); - string strError; - switch(code) - { - case -212: - strError = "Error choosing inputs for the send transaction"; - break; - case -233: - strError = "Error with redemption address"; - break; - case -220: - strError = "Error with redemption address key ID"; - break; - case -221: - strError = "Error obtaining public key for redemption address"; - break; - case -222: - strError = "Error public key for redemption address is not valid"; - break; - case -223: - strError = "Error validating redemption address"; - break; - case -205: - strError = "Error with wallet object"; - break; - case -206: - strError = "Error with selected inputs for the send transaction"; - break; - case -211: - strError = "Error creating transaction (wallet may be locked or fees may not be sufficient)"; - break; - case -213: - strError = "Error committing transaction"; - break; - } - if (strError.empty()) strError = "Error code does not have associated error text."; - QMessageBox::critical( this, "Send transaction failed", - "The send transaction has failed.\n\nThe error code was: " + QString::fromStdString(strCode) + "\nThe error message was:\n" + QString::fromStdString(strError)); - return; - } - else - { - // call an update of the balances -// set_wallet_totals(); -// updateBalances(); - - // display the result - string strSentText = "Your Master Protocol transaction has been sent.\n\nThe transaction ID is:\n\n"; - strSentText += tradeTXID.GetHex() + "\n\n"; - QString sentText = QString::fromStdString(strSentText); - QMessageBox sentDialog; - sentDialog.setIcon(QMessageBox::Information); - sentDialog.setWindowTitle("Transaction broadcast successfully"); - sentDialog.setText(sentText); - sentDialog.setStandardButtons(QMessageBox::Yes|QMessageBox::Ok); - sentDialog.setDefaultButton(QMessageBox::Ok); - sentDialog.setButtonText( QMessageBox::Yes, "Copy TXID to clipboard" ); - if(sentDialog.exec() == QMessageBox::Yes) - { - // copy TXID to clipboard - GUIUtil::setClipboard(QString::fromStdString(tradeTXID.GetHex())); - } - // clear the form -// clearFields(); - } - -} - - diff --git a/src/qt/metadexdialog.h b/src/qt/metadexdialog.h deleted file mode 100644 index e14ad0077183e..0000000000000 --- a/src/qt/metadexdialog.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef METADEXDIALOG_H -#define METADEXDIALOG_H - -#include "walletmodel.h" - -#include -#include -#include - -using boost::multiprecision::cpp_dec_float_100; - -class OptionsModel; - -QT_BEGIN_NAMESPACE -class QUrl; -QT_END_NAMESPACE - -namespace Ui { - class MetaDExDialog; -} - -/** Dialog for looking up Master Protocol tokens */ -class MetaDExDialog : public QDialog -{ - Q_OBJECT - -public: - void FullRefresh(); - void SwitchMarket(); - void UpdateSellAddress(); - void UpdateBuyAddress(); - void UpdateSellOffers(); - void UpdateBuyOffers(); - explicit MetaDExDialog(QWidget *parent = 0); - void setModel(WalletModel *model); - - /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). - */ - QWidget *setupTabChain(QWidget *prev); - - -public slots: - void switchButtonClicked(); - void sellAddressComboBoxChanged(int idx); - void buyAddressComboBoxChanged(int idx); - void sellClicked(int row, int col); - void buyClicked(int row, int col); - void sendTrade(bool sell); - void OrderRefresh(); - -private: - Ui::MetaDExDialog *ui; - WalletModel *model; - -private slots: - void buyRecalc(); - void sellRecalc(); - void buyTrade(); - void sellTrade(); - -signals: - // Fired when a message should be reported to the user - void message(const QString &title, const QString &message, unsigned int style); -}; - -#endif // METADEXDIALOG_H diff --git a/src/qt/orderhistorydialog.cpp b/src/qt/orderhistorydialog.cpp deleted file mode 100644 index aa9003af7ffc1..0000000000000 --- a/src/qt/orderhistorydialog.cpp +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright (c) 2011-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "orderhistorydialog.h" -#include "ui_orderhistorydialog.h" - -#include "guiutil.h" -#include "optionsmodel.h" -#include "walletmodel.h" -#include "wallet.h" -#include "base58.h" -#include "ui_interface.h" - -#include - -#include "leveldb/db.h" -#include "leveldb/write_batch.h" - -// potentially overzealous includes here -#include "base58.h" -#include "rpcserver.h" -#include "init.h" -#include "util.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "json/json_spirit_utils.h" -#include "json/json_spirit_value.h" -#include "leveldb/db.h" -#include "leveldb/write_batch.h" -// end potentially overzealous includes - -using namespace json_spirit; -#include "mastercore.h" -using namespace mastercore; - -// potentially overzealous using here -using namespace std; -using namespace boost; -using namespace boost::assign; -using namespace leveldb; -// end potentially overzealous using - -#include "mastercore_dex.h" -#include "mastercore_tx.h" -#include "mastercore_sp.h" -#include "mastercore_parse_string.h" -#include "mastercore_rpc.h" - -#include -#include -#include -#include -#include - -OrderHistoryDialog::OrderHistoryDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::orderHistoryDialog), - model(0) -{ - ui->setupUi(this); - - // setup - ui->orderHistoryTable->setColumnCount(7); - ui->orderHistoryTable->setHorizontalHeaderItem(0, new QTableWidgetItem(" ")); - ui->orderHistoryTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Date")); - ui->orderHistoryTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Status")); - ui->orderHistoryTable->setHorizontalHeaderItem(3, new QTableWidgetItem("Trade Details")); - ui->orderHistoryTable->setHorizontalHeaderItem(4, new QTableWidgetItem("Sold")); - ui->orderHistoryTable->setHorizontalHeaderItem(5, new QTableWidgetItem("Received")); - ui->orderHistoryTable->verticalHeader()->setVisible(false); - ui->orderHistoryTable->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->orderHistoryTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->orderHistoryTable->setSelectionMode(QAbstractItemView::SingleSelection); - ui->orderHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); - ui->orderHistoryTable->setColumnWidth(0, 23); - ui->orderHistoryTable->setColumnWidth(1, 150); - ui->orderHistoryTable->setColumnWidth(2, 100); - ui->orderHistoryTable->setColumnWidth(4, 180); - ui->orderHistoryTable->setColumnWidth(5, 180); - ui->orderHistoryTable->setColumnWidth(6, 0); - ui->orderHistoryTable->setContextMenuPolicy(Qt::CustomContextMenu); - - // Actions - QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this); - QAction *showDetailsAction = new QAction(tr("Show trade details"), this); - - contextMenu = new QMenu(); - contextMenu->addAction(copyTxIDAction); - contextMenu->addAction(showDetailsAction); - - // Connect actions - connect(ui->orderHistoryTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); - connect(ui->orderHistoryTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails())); - connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID())); - connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); - - Update(); -} - -void OrderHistoryDialog::Update() -{ - //pending orders - int rowcount = 0; - - // handle pending transactions first - for(PendingMap::iterator it = my_pending.begin(); it != my_pending.end(); ++it) - { - CMPPending *p_pending = &(it->second); - uint256 txid = it->first; - string txidStr = txid.GetHex(); - - string senderAddress = p_pending->src; - uint64_t propertyId = p_pending->prop; - bool divisible = isPropertyDivisible(propertyId); - string displayAmount; - int64_t amount = p_pending->amount; - string displayToken; - string displayValid; - string displayAddress = senderAddress; - int64_t type = p_pending->type; - if (type == 21) - { - if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } - QString txTimeStr = "Unconfirmed"; - string statusText = "Pending"; - string displayText = "Sell "; - string displayInToken; - string displayOutToken; - if(divisible) { displayText += FormatDivisibleShortMP(amount); } else { displayText += FormatIndivisibleMP(amount); } - if(propertyId < 3) - { - if(propertyId == 1) { displayText += " MSC"; displayOutToken = " MSC"; } - if(propertyId == 2) { displayText += " TMSC"; displayOutToken = " TMSC"; } - } - else - { - string s = to_string(propertyId); - displayText += " SPT#" + s + ""; - displayOutToken = " SPT#" + s; - } - displayText += " (awaiting confirmation)"; - string displayIn = "---"; - string displayOut = "---"; - //icon - QIcon ic = QIcon(":/icons/transaction_0"); - // add to history - ui->orderHistoryTable->setRowCount(rowcount+1); - QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); - QTableWidgetItem *statusCell = new QTableWidgetItem(QString::fromStdString(statusText)); - QTableWidgetItem *infoCell = new QTableWidgetItem(QString::fromStdString(displayText)); - QTableWidgetItem *amountOutCell = new QTableWidgetItem(QString::fromStdString(displayOut)); - QTableWidgetItem *amountInCell = new QTableWidgetItem(QString::fromStdString(displayIn)); - QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(txidStr)); - iconCell->setIcon(ic); - amountOutCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountOutCell->setForeground(QColor("#EE0000")); - amountInCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountInCell->setForeground(QColor("#00AA00")); - if (rowcount % 2) - { - dateCell->setBackground(QColor("#F0F0F0")); - statusCell->setBackground(QColor("#F0F0F0")); - infoCell->setBackground(QColor("#F0F0F0")); - amountOutCell->setBackground(QColor("#F0F0F0")); - amountInCell->setBackground(QColor("#F0F0F0")); - iconCell->setBackground(QColor("#F0F0F0")); - txidCell->setBackground(QColor("#F0F0F0")); - } - amountInCell->setForeground(QColor("#000000")); - amountOutCell->setForeground(QColor("#000000")); - - ui->orderHistoryTable->setItem(rowcount, 0, iconCell); - ui->orderHistoryTable->setItem(rowcount, 1, dateCell); - ui->orderHistoryTable->setItem(rowcount, 2, statusCell); - ui->orderHistoryTable->setItem(rowcount, 3, infoCell); - ui->orderHistoryTable->setItem(rowcount, 4, amountOutCell); - ui->orderHistoryTable->setItem(rowcount, 5, amountInCell); - ui->orderHistoryTable->setItem(rowcount, 6, txidCell); - rowcount += 1; - } - } - - - //wallet orders - CWallet *wallet = pwalletMain; - string sAddress = ""; - int64_t nStartBlock = 0; - int64_t nEndBlock = 999999; - - // rewrite to use original listtransactions methodology from core - LOCK(wallet->cs_wallet); - std::list acentries; - CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); - - // iterate backwards - for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) - { - CWalletTx *const pwtx = (*it).second.first; - if (pwtx != 0) - { - uint256 hash = pwtx->GetHash(); - CTransaction wtx; - uint256 blockHash = 0; - if (!GetTransaction(hash, wtx, blockHash, true)) continue; - // get the time of the tx - int64_t nTime = pwtx->GetTxTime(); - // get the height of the transaction and check it's within the chosen parameters - blockHash = pwtx->hashBlock; - if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue; - CBlockIndex* pBlockIndex = mapBlockIndex[blockHash]; - if (NULL == pBlockIndex) continue; - int blockHeight = pBlockIndex->nHeight; - if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range - // check if the transaction exists in txlist, and if so is it correct type (21) - if (p_txlistdb->exists(hash)) - { - // get type from levelDB - string strValue; - if (!p_txlistdb->getTX(hash, strValue)) continue; - std::vector vstr; - boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); - if (4 <= vstr.size()) - { - // if tx21, get the details for the list - if(21 == atoi(vstr[2])) - { - string statusText; - unsigned int propertyIdForSale = 0; - unsigned int propertyIdDesired = 0; - uint64_t amountForSale = 0; - uint64_t amountDesired = 0; - string address; - bool divisibleForSale = false; - bool divisibleDesired = false; - Array tradeArray; - uint64_t totalBought = 0; - uint64_t totalSold = 0; - bool orderOpen = false; - bool valid = false; - - CMPMetaDEx temp_metadexoffer; - CMPTransaction mp_obj; - int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); - if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity - { - if (0<=mp_obj.step1()) - { - //MPTxType = mp_obj.getTypeString(); - //MPTxTypeInt = mp_obj.getType(); - address = mp_obj.getSender(); - //if (!filterAddress.empty()) if ((senderAddress != filterAddress) && (refAddress != filterAddress)) return -1; // return negative rc if filtering & no match - - int tmpblock=0; - uint32_t tmptype=0; - uint64_t amountNew=0; - valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew); - - if (0 == mp_obj.step2_Value()) - { - propertyIdForSale = mp_obj.getProperty(); - amountForSale = mp_obj.getAmount(); - divisibleForSale = isPropertyDivisible(propertyIdForSale); - if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) - { - propertyIdDesired = temp_metadexoffer.getDesProperty(); - divisibleDesired = isPropertyDivisible(propertyIdDesired); - amountDesired = temp_metadexoffer.getAmountDesired(); - //mdex_action = temp_metadexoffer.getAction(); - t_tradelistdb->getMatchingTrades(hash, propertyIdForSale, &tradeArray, &totalSold, &totalBought); - - // status - is order cancelled/closed-filled/open/open-partialfilled? - // is the sell offer still open - need more efficient way to do this - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - if (my_it->first == propertyIdForSale) //at minimum only go deeper if it's the right property id - { - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - md_Set & indexes = (it->second); - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - if( obj.getHash().GetHex() == hash.GetHex() ) orderOpen = true; - } - } - } - } - } - } - } - } - - // work out status - bool partialFilled = false; - bool filled = false; - if(totalSold>0) partialFilled = true; - if(totalSold>=amountForSale) filled = true; - statusText = "Unknown"; - if((!orderOpen) && (!partialFilled)) statusText = "Cancelled"; - if((!orderOpen) && (partialFilled)) statusText = "Part Cancel"; - if((!orderOpen) && (filled)) statusText = "Filled"; - if((orderOpen) && (!partialFilled)) statusText = "Open"; - if((orderOpen) && (partialFilled)) statusText = "Part Filled"; - - // add to list - string displayText = "Sell "; - string displayIn = ""; - string displayOut = "-"; - string displayInToken; - string displayOutToken; - - if(divisibleForSale) { displayText += FormatDivisibleShortMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); } - if(propertyIdForSale < 3) - { - if(propertyIdForSale == 1) { displayText += " MSC for "; displayOutToken = " MSC"; } - if(propertyIdForSale == 2) { displayText += " TMSC for "; displayOutToken = " TMSC"; } - } - else - { - string s = to_string(propertyIdForSale); - displayText += " SPT#" + s + " for "; - displayOutToken = " SPT#" + s; - } - if(divisibleDesired) { displayText += FormatDivisibleShortMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); } - if(propertyIdDesired < 3) - { - if(propertyIdDesired == 1) { displayText += " MSC"; displayInToken = " MSC"; } - if(propertyIdDesired == 2) { displayText += " TMSC"; displayInToken = " TMSC"; } - } - else - { - string s = to_string(propertyIdDesired); - displayText += " SPT#" + s; - displayInToken = " SPT#" + s; - } - if(divisibleDesired) { displayIn += FormatDivisibleShortMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); } - if(divisibleForSale) { displayOut += FormatDivisibleShortMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); } - if(totalBought == 0) displayIn = "0"; - if(totalSold == 0) displayOut = "0"; - displayIn += displayInToken; - displayOut += displayOutToken; - QDateTime txTime; - txTime.setTime_t(nTime); - QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); - - //icon - QIcon ic = QIcon(":/icons/transaction_0"); - if(statusText == "Cancelled") ic =QIcon(":/icons/meta_cancelled"); - if(statusText == "Part Cancel") ic = QIcon(":/icons/meta_partialclosed"); - if(statusText == "Filled") ic = QIcon(":/icons/meta_filled"); - if(statusText == "Open") ic = QIcon(":/icons/meta_open"); - if(statusText == "Part Filled") ic = QIcon(":/icons/meta_partial"); - if(!valid) ic = QIcon(":/icons/transaction_invalid"); - // add to order history - ui->orderHistoryTable->setRowCount(rowcount+1); - QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); - QTableWidgetItem *statusCell = new QTableWidgetItem(QString::fromStdString(statusText)); - QTableWidgetItem *infoCell = new QTableWidgetItem(QString::fromStdString(displayText)); - QTableWidgetItem *amountOutCell = new QTableWidgetItem(QString::fromStdString(displayOut)); - QTableWidgetItem *amountInCell = new QTableWidgetItem(QString::fromStdString(displayIn)); - QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); - iconCell->setIcon(ic); - //addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); - //addressCell->setForeground(QColor("#707070")); - amountOutCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountOutCell->setForeground(QColor("#EE0000")); - amountInCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountInCell->setForeground(QColor("#00AA00")); - if (rowcount % 2) - { - dateCell->setBackground(QColor("#F0F0F0")); - statusCell->setBackground(QColor("#F0F0F0")); - infoCell->setBackground(QColor("#F0F0F0")); - amountOutCell->setBackground(QColor("#F0F0F0")); - amountInCell->setBackground(QColor("#F0F0F0")); - iconCell->setBackground(QColor("#F0F0F0")); - txidCell->setBackground(QColor("#F0F0F0")); - } - if((!orderOpen) && (filled)) //make filled orders background - { - dateCell->setForeground(QColor("#707070")); - statusCell->setForeground(QColor("#707070")); - infoCell->setForeground(QColor("#707070")); - amountOutCell->setForeground(QColor("#993333")); - amountInCell->setForeground(QColor("#006600")); - } - if(displayIn.substr(0,2) == "0 ") amountInCell->setForeground(QColor("#000000")); - if(displayOut.substr(0,2) == "0 ") amountOutCell->setForeground(QColor("#000000")); - - ui->orderHistoryTable->setItem(rowcount, 0, iconCell); - ui->orderHistoryTable->setItem(rowcount, 1, dateCell); - ui->orderHistoryTable->setItem(rowcount, 2, statusCell); - ui->orderHistoryTable->setItem(rowcount, 3, infoCell); - ui->orderHistoryTable->setItem(rowcount, 4, amountOutCell); - ui->orderHistoryTable->setItem(rowcount, 5, amountInCell); - ui->orderHistoryTable->setItem(rowcount, 6, txidCell); - rowcount += 1; - } - } - } - } - } -} - -void OrderHistoryDialog::setModel(WalletModel *model) -{ - this->model = model; - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(Update())); -} - -void OrderHistoryDialog::contextualMenu(const QPoint &point) -{ - QModelIndex index = ui->orderHistoryTable->indexAt(point); - if(index.isValid()) - { - contextMenu->exec(QCursor::pos()); - } -} - -void OrderHistoryDialog::copyTxID() -{ - GUIUtil::setClipboard(ui->orderHistoryTable->item(ui->orderHistoryTable->currentRow(),6)->text()); -} - -void OrderHistoryDialog::showDetails() -{ - Object txobj; - uint256 txid; - txid.SetHex(ui->orderHistoryTable->item(ui->orderHistoryTable->currentRow(),6)->text().toStdString()); - std::string strTXText; - - // first of all check if the TX is a pending tx, if so grab details from pending map - PendingMap::iterator it = my_pending.find(txid); - if (it != my_pending.end()) - { - CMPPending *p_pending = &(it->second); - strTXText = "*** THIS TRANSACTION IS UNCONFIRMED ***\n" + p_pending->desc; - } - else - { - // grab details usual way - int pop = populateRPCTransactionObject(txid, &txobj, ""); - if (0<=pop) - { - Object tradeobj; - CMPMetaDEx temp_metadexoffer; - string senderAddress; - unsigned int propertyId = 0; - CTransaction wtx; - uint256 blockHash = 0; - if (!GetTransaction(txid, wtx, blockHash, true)) { return; } - CMPTransaction mp_obj; - int parseRC = parseTransaction(true, wtx, 0, 0, &mp_obj); - if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sa$ - { - if (0<=mp_obj.step1()) - { - senderAddress = mp_obj.getSender(); - if (0 == mp_obj.step2_Value()) - { - propertyId = mp_obj.getProperty(); - } - } - } - // get the amount for sale in this sell offer to see if filled - uint64_t amountForSale = mp_obj.getAmount(); - - // create array of matches - Array tradeArray; - uint64_t totalBought = 0; - uint64_t totalSold = 0; - t_tradelistdb->getMatchingTrades(txid, propertyId, &tradeArray, &totalSold, &totalBought); - - // get action byte - int actionByte = 0; - if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) { actionByte = (int)temp_metadexoffer.getAction(); } - - // everything seems ok, now add status and get an array of matches to add to the object - // work out status - bool orderOpen = isMetaDExOfferActive(txid, propertyId); - bool partialFilled = false; - bool filled = false; - string statusText; - if(totalSold>0) partialFilled = true; - if(totalSold>=amountForSale) filled = true; - statusText = "unknown"; - if((!orderOpen) && (!partialFilled)) statusText = "cancelled"; // offers that are closed but not filled must have been cancelled - if((!orderOpen) && (partialFilled)) statusText = "cancelled part filled"; // offers that are closed but not filled must have been cancelled - if((!orderOpen) && (filled)) statusText = "filled"; // filled offers are closed - if((orderOpen) && (!partialFilled)) statusText = "open"; // offer exists but no matches yet - if((orderOpen) && (partialFilled)) statusText = "open part filled"; // offer exists, some matches but not filled yet - if(actionByte==1) txobj.push_back(Pair("status", statusText)); // no status for cancel txs - - // add cancels array to object and set status as cancelled only if cancel type - if(actionByte != 1) - { - Array cancelArray; - int numberOfCancels = p_txlistdb->getNumberOfMetaDExCancels(txid); - if (0getKeyValue(txid.ToString() + "-C" + to_string(refNumber)); - if (!strValue.empty()) - { - std::vector vstr; - boost::split(vstr, strValue, boost::is_any_of(":"), token_compress_on); - if (3 <= vstr.size()) - { - uint64_t propId = boost::lexical_cast(vstr[1]); - uint64_t amountUnreserved = boost::lexical_cast(vstr[2]); - cancelTx.push_back(Pair("txid", vstr[0])); - cancelTx.push_back(Pair("propertyid", propId)); - cancelTx.push_back(Pair("amountunreserved", FormatMP(propId, amountUnreserved))); - cancelArray.push_back(cancelTx); - } - } - } - } - txobj.push_back(Pair("cancelledtransactions", cancelArray)); - } - else - { - // if cancelled, show cancellation txid - if((statusText == "cancelled") || (statusText == "cancelled part filled")) { txobj.push_back(Pair("canceltxid", p_txlistdb->findMetaDExCancel(txid).GetHex())); } - // add matches array to object - txobj.push_back(Pair("matches", tradeArray)); // only action 1 offers can have matches - } - strTXText = write_string(Value(txobj), false) + "\n"; - } - } - - if (!strTXText.empty()) - { - // clean up - string from = ","; - string to = ",\n "; - size_t start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = ":"; - to = " : "; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "{"; - to = "{\n "; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "}"; - to = "\n}"; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "["; - to = "[\n"; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - from = "]"; - to = "\n]"; - start_pos = 0; - while((start_pos = strTXText.find(from, start_pos)) != std::string::npos) - { - strTXText.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - - QString txText = QString::fromStdString(strTXText); - QDialog *txDlg = new QDialog; - QLayout *dlgLayout = new QVBoxLayout; - dlgLayout->setSpacing(12); - dlgLayout->setMargin(12); - QTextEdit *dlgTextEdit = new QTextEdit; - dlgTextEdit->setText(txText); - dlgTextEdit->setStatusTip("Transaction Information"); - dlgLayout->addWidget(dlgTextEdit); - txDlg->setWindowTitle("Transaction Information"); - QPushButton *closeButton = new QPushButton(tr("&Close")); - closeButton->setDefault(true); - QDialogButtonBox *buttonBox = new QDialogButtonBox; - buttonBox->addButton(closeButton, QDialogButtonBox::AcceptRole); - dlgLayout->addWidget(buttonBox); - txDlg->setLayout(dlgLayout); - txDlg->resize(700, 360); - connect(buttonBox, SIGNAL(accepted()), txDlg, SLOT(accept())); - txDlg->setAttribute(Qt::WA_DeleteOnClose); //delete once it's closed - if (txDlg->exec() == QDialog::Accepted) { } else { } //do nothing but close - } -} - diff --git a/src/qt/orderhistorydialog.h b/src/qt/orderhistorydialog.h deleted file mode 100644 index b029c19916aff..0000000000000 --- a/src/qt/orderhistorydialog.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef ORDERHISTORYDIALOG_H -#define ORDERHISTORYDIALOG_H - -#include "walletmodel.h" - -#include -#include -#include -#include -#include -#include - -class OptionsModel; - -QT_BEGIN_NAMESPACE -class QUrl; -QT_END_NAMESPACE - -namespace Ui { - class orderHistoryDialog; -} - -/** Dialog for looking up Master Protocol tokens */ -class OrderHistoryDialog : public QDialog -{ - Q_OBJECT - -public: - //void FullRefresh(); - explicit OrderHistoryDialog(QWidget *parent = 0); - void setModel(WalletModel *model); - - /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). - */ - QWidget *setupTabChain(QWidget *prev); - // QDialog *txDlg; - QTableWidgetItem *iconCell; - QTableWidgetItem *dateCell; - QTableWidgetItem *statusCell; - QTableWidgetItem *Cell; - QTableWidgetItem *amountOutCell; - QTableWidgetItem *amountInCell; - QTableWidgetItem *txidCell; - QLayout *dlgLayout; - QTextEdit *dlgTextEdit; - QDialogButtonBox *buttonBox; - QPushButton *closeButton; - - -public slots: - void Update(); - void contextualMenu(const QPoint &); - void showDetails(); - void copyTxID(); - -private: - Ui::orderHistoryDialog *ui; - WalletModel *model; - QMenu *contextMenu; - -private slots: - //void buyRecalc(); - -signals: - // Fired when a message should be reported to the user - void message(const QString &title, const QString &message, unsigned int style); -}; - -#endif // ORDERHISTORYDIALOG_H From 280357e0c44c143c3cd0c60613257e31d1297752 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 11 Dec 2014 20:24:19 -0800 Subject: [PATCH 115/141] Remove additional unused metadex UI components --- src/qt/forms/metadexcanceldialog.ui | 223 --------- src/qt/forms/metadexdialog.ui | 674 ---------------------------- src/qt/forms/orderhistorydialog.ui | 31 -- 3 files changed, 928 deletions(-) delete mode 100644 src/qt/forms/metadexcanceldialog.ui delete mode 100644 src/qt/forms/metadexdialog.ui delete mode 100644 src/qt/forms/orderhistorydialog.ui diff --git a/src/qt/forms/metadexcanceldialog.ui b/src/qt/forms/metadexcanceldialog.ui deleted file mode 100644 index 534ec95933730..0000000000000 --- a/src/qt/forms/metadexcanceldialog.ui +++ /dev/null @@ -1,223 +0,0 @@ - - - MetaDExCancelDialog - - - - 0 - 0 - 664 - 474 - - - - Form - - - - - - 0 - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - 0 - - - - - - 75 - true - - - - padding-bottom:4px; - - - Cancellation Type: - - - - - - - padding-left:10px; - - - Cancel by pair - - - - - - - padding-left:10px; - - - Cancel by price - - - - - - - padding-left:10px; - - - Cancel everything - - - - - - - - 75 - true - - - - padding-top:10px;padding-bottom:4px; - - - Cancellation Criteria: - - - - - - - 0 - - - 10 - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 8 - 20 - - - - - - - - - 0 - 0 - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 8 - 20 - - - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Send Cancel Request - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 8 - 20 - - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/src/qt/forms/metadexdialog.ui b/src/qt/forms/metadexdialog.ui deleted file mode 100644 index 0eb1160a2a6b6..0000000000000 --- a/src/qt/forms/metadexdialog.ui +++ /dev/null @@ -1,674 +0,0 @@ - - - MetaDExDialog - - - - 0 - 0 - 704 - 474 - - - - Form - - - - - - false - - - background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; - - - true - - - 3 - - - - - - - 0 - - - 0 - - - 0 - - - - - 0 - - - 10 - - - - - 6 - - - 10 - - - 0 - - - - - 6 - - - 0 - - - - - - 75 - true - - - - Trade MaidSafeCoin (#3) for Mastercoin - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 10 - 20 - - - - - - - - - 50 - false - - - - Switch Markets: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 80 - 0 - - - - Switch - - - - - - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - 75 - true - - - - BUY SP#3 - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Your Balance 0.000000000 MSC - - - - - - - - - 0 - - - - - Address: - - - - - - - - 0 - 0 - - - - - - - - - - 0 - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 0 - - - - - Amount (SPT): - - - - - - - - - - - - - Price Per SPT: - - - - - - - - - 0 - - - 0 - - - - - 0 - - - 0 - - - - - SPT - - - - - - - TMSC - - - - - - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Total Price: - - - - - - - - 75 - true - - - - 0.00000000 MSC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Buy SP#3 - - - - - - - - - 0 - - - - - - 75 - true - - - - SELL OFFERS - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 75 - true - - - - SELL SP#3 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Your Balance 0.000000000 SPT - - - - - - - - - 0 - - - - - Address: - - - - - - - - 0 - 0 - - - - - - - - - - 0 - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 6 - - - - - Amount (SPT): - - - - - - - - - - Price Per SPT: - - - - - - - - - - - - 0 - - - 0 - - - - - 0 - - - 0 - - - - - SPT - - - - - - - TMSC - - - - - - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Total Price: - - - - - - - - 75 - true - - - - 0.00000000 MSC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Sell SP#3 - - - - - - - - - 0 - - - - - - 75 - true - - - - BUY OFFERS - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - - - - - 75 - true - - - - color:rgb(167, 125, 19) - - - * YOU HAVE TRANSACTIONS WAITING FOR CONFIRMATION * - - - Qt::AlignCenter - - - - - - - - diff --git a/src/qt/forms/orderhistorydialog.ui b/src/qt/forms/orderhistorydialog.ui deleted file mode 100644 index 9724274c1f1cb..0000000000000 --- a/src/qt/forms/orderhistorydialog.ui +++ /dev/null @@ -1,31 +0,0 @@ - - - orderHistoryDialog - - - - 0 - 0 - 664 - 474 - - - - Form - - - - - - 0 - - - - - - - - - - - From a09bca5cd6dd8aa82516c527a0ac95a5c6c692fd Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 11 Dec 2014 20:47:14 -0800 Subject: [PATCH 116/141] Change versioning to seperate file --- src/mastercore.cpp | 1 + src/mastercore.h | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 5d2d20d88d5ef..d59b2544d40ce 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -77,6 +77,7 @@ using namespace mastercore; #include "mastercore_tx.h" #include "mastercore_sp.h" #include "mastercore_errors.h" +#include "mastercore_version.h" // part of 'breakout' feature static const int nBlockTop = 0; diff --git a/src/mastercore.h b/src/mastercore.h index ff57210fc8d98..30acf107a3c0d 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -21,10 +21,6 @@ int const MAX_STATE_HISTORY = 50; #define TEST_ECO_PROPERTY_1 (0x80000003UL) -// define the version for alert messages -#define OMNICORE_VERSION_BASE 90 // 82 = 0.0.8.2 91 = 0.0.9.1 103 = 0.0.10.3 etc -#define OMNICORE_VERSION_TYPE "-dev" // switch to -rel for tags, switch back to -dev for development - // could probably also use: int64_t maxInt64 = std::numeric_limits::max(); // maximum numeric values from the spec: #define MAX_INT_8_BYTES (9223372036854775807UL) From 2ee9140e4a8eae01bbba8e42ef7f48d62edc384e Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 11 Dec 2014 20:47:50 -0800 Subject: [PATCH 117/141] Further fixes for versioning --- src/Makefile.am | 1 + src/mastercore_rpc.cpp | 2 +- src/mastercore_version.h | 25 +++++++++++++++++++++++++ src/qt/splashscreen.cpp | 6 +++++- src/qt/utilitydialog.cpp | 4 +++- 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/mastercore_version.h diff --git a/src/Makefile.am b/src/Makefile.am index 96994bc31bbfe..2eb247c7c1c2f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ BITCOIN_CORE_H = \ mastercore_rpc.h \ mastercore_sp.h \ mastercore_errors.h \ + mastercore_version.h \ crypter.h \ db.h \ hash.h \ diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 23873493ab893..51d9b40dbc966 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -42,6 +42,7 @@ using namespace mastercore; #include "mastercore_sp.h" #include "mastercore_errors.h" #include "mastercore_rpc.h" +#include "mastercore_version.h" void PropertyToJSON(const CMPSPInfo::Entry& sProperty, Object& property_obj) { @@ -2021,7 +2022,6 @@ Value getsto_MP(const Array& params, bool fHelp) if (propertyId == 0) // something went wrong, couldn't decode property ID - bad packet? throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); - bool divisible = isPropertyDivisible(propertyId); // make a request to new RPC populator function to populate a transaction object int populateResult = populateRPCTransactionObject(hash, &txobj); // check the response, throw any error codes if false diff --git a/src/mastercore_version.h b/src/mastercore_version.h new file mode 100644 index 0000000000000..6bce0e58b13fd --- /dev/null +++ b/src/mastercore_version.h @@ -0,0 +1,25 @@ +// Copyright (c) 2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _MASTERCORE_VERSION_H +#define _MASTERCORE_VERSION_H + + #define OMNICORE_VERSION_BASE 90 // 82 = 0.0.8.2 91 = 0.0.9.1 103 = 0.0.10.3 etc + #define OMNICORE_VERSION_TYPE "-dev" // switch to -rel for tags, switch back to -dev for development + + /* use this when we tag 0.0.9 + #define OMNICORE_VERSION_BASE 90 + #define OMNICORE_VERSION_TYPE "-rel" + */ + + /* after tagging switch it onto the next dev version + #define OMNICORE_VERSION_BASE 91 + #define OMNICORE_VERSION_TYPE "-dev" + */ + +#endif + + + + diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 95a4488614c2b..bc38bd2cc6892 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -15,6 +15,9 @@ #include #include +#include +#include "mastercore_version.h" + SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet) : QSplashScreen(pixmap, f) { @@ -30,8 +33,9 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest float fontFactor = 1.0; // define text to place + string coreVersionStr = "Experimental UI 0.0." + boost::lexical_cast((double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE; QString titleText = tr("Master Core"); - QString versionText = QString("Experimental UI Alpha 0.0002b"); //QString("Version %1").arg(QString::fromStdString(FormatFullVersion())); + QString versionText = QString::fromStdString(coreVersionStr); QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); QString copyrightMSC = QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index eab466c179b8e..a8a6a7ae484f7 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include "mastercore_version.h" /** "About" dialog box */ AboutDialog::AboutDialog(QWidget *parent) : @@ -34,7 +36,7 @@ void AboutDialog::setModel(ClientModel *model) { if(model) { - QString version = "0.0.9"; //hardcoded for now + QString version = QString::fromStdString("0.0." + boost::lexical_cast((double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE); /* On x86 add a bit specifier to the version so that users can distinguish between * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. */ From 7e5e95e114a223baaa678a4dd5f906d774384f42 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Fri, 12 Dec 2014 19:33:13 -0800 Subject: [PATCH 118/141] Fix UI history SP# display for 'Create Property' types --- src/qt/txhistorydialog.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 2cb297425a32f..069317a4708be 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -352,6 +352,16 @@ void TXHistoryDialog::UpdateHistory() { propertyId = mp_obj.getProperty(); amount = mp_obj.getAmount(); + // special case for property creation (getProperty cannot get ID as createdID not stored in obj) + if (valid) // we only generate an ID for valid creates + { + if ((mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_FIXED) || + (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_VARIABLE) || + (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_MANUAL)) + { + propertyId = _my_sps->findSPByTX(hash); + } + } divisible = isPropertyDivisible(propertyId); } } @@ -406,7 +416,17 @@ void TXHistoryDialog::UpdateHistory() txTime.setTime_t(nTime); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); if (IsMyAddress(senderAddress)) displayAmount = "-" + displayAmount; - //icon + // override/hide display amount for invalid creates, we can't display amount and property as no prop exists + if (!valid) + { + if ((mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_FIXED) || + (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_VARIABLE) || + (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_MANUAL)) + { + displayAmount = "N/A"; + } + } + // icon QIcon ic = QIcon(":/icons/transaction_0"); int confirmations = 1 + GetHeight() - pBlockIndex->nHeight; switch(confirmations) From c7710f9296a852e619697a59e5856db715aef432 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Fri, 12 Dec 2014 22:56:14 -0800 Subject: [PATCH 119/141] Change the way locks are used to avoid hangs waiting for locks --- src/mastercore.cpp | 1 + src/mastercore.h | 1 + src/qt/txhistorydialog.cpp | 17 ++++++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index d59b2544d40ce..ecc2f9ba1f0a3 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -119,6 +119,7 @@ int msc_debug_persistence = 0; int msc_debug_metadex = 1; int msc_debug_metadex2= 1; int msc_debug_metadex3= 0; // enable this to see the orderbook before & after each TX +int msc_debug_ui = 1; static int disable_Divs = 0; static int disableLevelDB = 0; diff --git a/src/mastercore.h b/src/mastercore.h index 30acf107a3c0d..214e7ccac594c 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -189,6 +189,7 @@ int64_t feeCheck(const string &address); const std::string ExodusAddress(); extern int msc_debug_dex; +extern int msc_debug_ui; extern CCriticalSection cs_tally; diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 069317a4708be..cd0952eb8320c 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -205,6 +205,8 @@ void TXHistoryDialog::UpdateHistory() int64_t nStartBlock = 0; int64_t nEndBlock = 999999; + int chainHeight = GetHeight(); + Array response; //prep an array to hold our output // STO has no inbound transaction, so we need to use an insert methodology here @@ -214,12 +216,17 @@ void TXHistoryDialog::UpdateHistory() boost::split(vecReceipts, mySTOReceipts, boost::is_any_of(","), token_compress_on); int64_t lastTXBlock = 999999; - // rewrite to use original listtransactions methodology from core - LOCK(wallet->cs_wallet); + // try and fix intermittent freeze on startup and while running by only updating if we can get required locks + // avoid hang waiting for locks + TRY_LOCK(cs_main,lckMain); + if (!lckMain) return; + TRY_LOCK(wallet->cs_wallet, lckWallet); + if (!lckWallet) return; + std::list acentries; CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*"); - // iterate backwards + // iterate backwards for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; @@ -269,7 +276,7 @@ void TXHistoryDialog::UpdateHistory() uint64_t total = 0; s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &total); // get matching receipts QIcon ic = QIcon(":/icons/transaction_0"); - int confirmations = 1 + GetHeight() - pBlkIdx->nHeight; + int confirmations = 1 + chainHeight - pBlkIdx->nHeight; switch(confirmations) { case 1: ic = QIcon(":/icons/transaction_1"); break; @@ -428,7 +435,7 @@ void TXHistoryDialog::UpdateHistory() } // icon QIcon ic = QIcon(":/icons/transaction_0"); - int confirmations = 1 + GetHeight() - pBlockIndex->nHeight; + int confirmations = 1 + chainHeight - pBlockIndex->nHeight; switch(confirmations) { case 1: ic = QIcon(":/icons/transaction_1"); break; From c135ec9ad10f54d2804c2c7ce1acb8380d52e2ae Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sat, 13 Dec 2014 18:45:10 -0800 Subject: [PATCH 120/141] Redo transaction history page to correct a bunch of bugs --- src/qt/txhistorydialog.cpp | 348 ++++++++++++++++++------------------- src/qt/txhistorydialog.h | 1 + 2 files changed, 166 insertions(+), 183 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index cd0952eb8320c..4f74e7f7952ff 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -124,6 +124,50 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : UpdateHistory(); } +void TXHistoryDialog::CreateRow(int rowcount, bool valid, bool bInbound, int confirmations, std::string txTimeStr, std::string displayType, std::string displayAddress, std::string displayAmount, std::string txidStr, bool fundsMoved) +{ + QIcon ic = QIcon(":/icons/transaction_0"); + switch(confirmations) + { + case 1: ic = QIcon(":/icons/transaction_1"); break; + case 2: ic = QIcon(":/icons/transaction_2"); break; + case 3: ic = QIcon(":/icons/transaction_3"); break; + case 4: ic = QIcon(":/icons/transaction_4"); break; + case 5: ic = QIcon(":/icons/transaction_5"); break; + } + if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); + if (!valid) ic = QIcon(":/icons/transaction_invalid"); + ui->txHistoryTable->setRowCount(rowcount+1); + QTableWidgetItem *dateCell = new QTableWidgetItem(QString::fromStdString(txTimeStr)); + QTableWidgetItem *typeCell = new QTableWidgetItem(QString::fromStdString(displayType)); + QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); + QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount)); + QTableWidgetItem *iconCell = new QTableWidgetItem; + QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(txidStr)); + iconCell->setIcon(ic); + addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); + addressCell->setForeground(QColor("#707070")); + amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); + amountCell->setForeground(QColor("#EE0000")); + if (bInbound) amountCell->setForeground(QColor("#00AA00")); + if (!fundsMoved) amountCell->setForeground(QColor("#404040")); + if (rowcount % 2) + { + amountCell->setBackground(QColor("#F0F0F0")); + addressCell->setBackground(QColor("#F0F0F0")); + dateCell->setBackground(QColor("#F0F0F0")); + typeCell->setBackground(QColor("#F0F0F0")); + txidCell->setBackground(QColor("#F0F0F0")); + iconCell->setBackground(QColor("#F0F0F0")); + } + ui->txHistoryTable->setItem(rowcount, 0, iconCell); + ui->txHistoryTable->setItem(rowcount, 1, dateCell); + ui->txHistoryTable->setItem(rowcount, 2, typeCell); + ui->txHistoryTable->setItem(rowcount, 3, addressCell); + ui->txHistoryTable->setItem(rowcount, 4, amountCell); + ui->txHistoryTable->setItem(rowcount, 5, txidCell); +} + void TXHistoryDialog::UpdateHistory() { int rowcount = 0; @@ -134,65 +178,32 @@ void TXHistoryDialog::UpdateHistory() CMPPending *p_pending = &(it->second); uint256 txid = it->first; string txidStr = txid.GetHex(); - //p_pending->print(txid); - string senderAddress = p_pending->src; uint64_t propertyId = p_pending->prop; bool divisible = isPropertyDivisible(propertyId); string displayAmount; int64_t amount = p_pending->amount; - string displayToken; string displayValid; string displayAddress = senderAddress; int64_t type = p_pending->type; - if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } - if (propertyId < 3) { - if(propertyId == 1) { displayToken = " MSC"; } - if(propertyId == 2) { displayToken = " TMSC"; } + if(propertyId == 1) { displayAmount += " MSC"; } + if(propertyId == 2) { displayAmount += " TMSC"; } } else { string s = to_string(propertyId); - displayToken = " SPT#" + s; + displayAmount += " SPT#" + s; } QString txTimeStr = "Unconfirmed"; string displayType; - if (type == 0) displayType = "Send"; + bool fundsMoved = false; + if (type == 0) { displayType = "Send"; fundsMoved = true; } if (type == 21) displayType = "MetaDEx Trade"; displayAmount = "-" + displayAmount; //all pending are outbound - //icon - QIcon ic = QIcon(":/icons/transaction_0"); - // add to history - ui->txHistoryTable->setRowCount(rowcount+1); - QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); - QTableWidgetItem *typeCell = new QTableWidgetItem(QString::fromStdString(displayType)); - QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); - QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); - QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(txidStr)); //hash.GetHex())); - iconCell->setIcon(ic); - addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); - addressCell->setForeground(QColor("#707070")); - amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountCell->setForeground(QColor("#EE0000")); - if (rowcount % 2) - { - amountCell->setBackground(QColor("#F0F0F0")); - addressCell->setBackground(QColor("#F0F0F0")); - dateCell->setBackground(QColor("#F0F0F0")); - typeCell->setBackground(QColor("#F0F0F0")); - txidCell->setBackground(QColor("#F0F0F0")); - iconCell->setBackground(QColor("#F0F0F0")); - } - ui->txHistoryTable->setItem(rowcount, 0, iconCell); - ui->txHistoryTable->setItem(rowcount, 1, dateCell); - ui->txHistoryTable->setItem(rowcount, 2, typeCell); - ui->txHistoryTable->setItem(rowcount, 3, addressCell); - ui->txHistoryTable->setItem(rowcount, 4, amountCell); - ui->txHistoryTable->setItem(rowcount, 5, txidCell); + CreateRow(rowcount, true, false, 0, "Unconfirmed", displayType, displayAddress, displayAmount, txidStr, fundsMoved); rowcount += 1; } @@ -272,58 +283,19 @@ void TXHistoryDialog::UpdateHistory() CBlockIndex* pBlkIdx = chainActive[atoi(svstr[1])]; txTime.setTime_t(pBlkIdx->GetBlockTime()); QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + string displayAmount; Array receiveArray; uint64_t total = 0; s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &total); // get matching receipts - QIcon ic = QIcon(":/icons/transaction_0"); int confirmations = 1 + chainHeight - pBlkIdx->nHeight; - switch(confirmations) - { - case 1: ic = QIcon(":/icons/transaction_1"); break; - case 2: ic = QIcon(":/icons/transaction_2"); break; - case 3: ic = QIcon(":/icons/transaction_3"); break; - case 4: ic = QIcon(":/icons/transaction_4"); break; - case 5: ic = QIcon(":/icons/transaction_5"); break; - } - if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); - string displayAmount; - string displayToken; if (divisible) { displayAmount = FormatDivisibleShortMP(total); } else { displayAmount = FormatIndivisibleMP(total); } if (propertyId < 3) { - if(propertyId == 1) { displayToken = " MSC"; } else { displayToken = " TMSC"; } + if(propertyId == 1) { displayAmount += " MSC"; } else { displayAmount += " TMSC"; } } else { string s = to_string(propertyId); - displayToken = " SPT#" + s; + displayAmount += " SPT#" + s; } - - // add to history - ui->txHistoryTable->setRowCount(rowcount+1); - QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); - QTableWidgetItem *typeCell = new QTableWidgetItem("STO Receive"); - QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); - QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); - QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); - iconCell->setIcon(ic); - addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); - addressCell->setForeground(QColor("#707070")); - amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountCell->setForeground(QColor("#00AA00")); - if (rowcount % 2) - { - amountCell->setBackground(QColor("#F0F0F0")); - addressCell->setBackground(QColor("#F0F0F0")); - dateCell->setBackground(QColor("#F0F0F0")); - typeCell->setBackground(QColor("#F0F0F0")); - txidCell->setBackground(QColor("#F0F0F0")); - iconCell->setBackground(QColor("#F0F0F0")); - } - ui->txHistoryTable->setItem(rowcount, 0, iconCell); - ui->txHistoryTable->setItem(rowcount, 1, dateCell); - ui->txHistoryTable->setItem(rowcount, 2, typeCell); - ui->txHistoryTable->setItem(rowcount, 3, addressCell); - ui->txHistoryTable->setItem(rowcount, 4, amountCell); - ui->txHistoryTable->setItem(rowcount, 5, txidCell); + CreateRow(rowcount, true, true, confirmations, txTimeStr.toStdString(), "STO Receive", displayAddress, displayAmount, hash.GetHex(), true); rowcount += 1; } } @@ -343,7 +315,55 @@ void TXHistoryDialog::UpdateHistory() CMPTransaction mp_obj; int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj); - if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity + string displayAmount; + string displayToken; + string displayValid; + string displayAddress; + string displayType; + if (0 < parseRC) //positive RC means payment + { + string tmpBuyer; + string tmpSeller; + uint64_t total = 0; + uint64_t tmpVout = 0; + uint64_t tmpNValue = 0; + uint64_t tmpPropertyId = 0; + p_txlistdb->getPurchaseDetails(hash,1,&tmpBuyer,&tmpSeller,&tmpVout,&tmpPropertyId,&tmpNValue); + senderAddress = tmpBuyer; + refAddress = tmpSeller; + bool bIsBuy = IsMyAddress(senderAddress); + if (!bIsBuy) + { + displayType = "DEx Sell"; + displayAddress = refAddress; + } + else + { + displayType = "DEx Buy"; + displayAddress = senderAddress; + } + // calculate total bought/sold + int numberOfPurchases=p_txlistdb->getNumberOfPurchases(hash); + if (0getPurchaseDetails(hash,purchaseNumber,&tmpBuyer,&tmpSeller,&tmpVout,&tmpPropertyId,&tmpNValue); + total += tmpNValue; + } + displayAmount = FormatDivisibleShortMP(total); + if(tmpPropertyId == 1) { displayAmount += " MSC"; } + if(tmpPropertyId == 2) { displayAmount += " TMSC"; } + QDateTime txTime; + txTime.setTime_t(nTime); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + if (!bIsBuy) displayAmount = "-" + displayAmount; + int confirmations = 1 + chainHeight - pBlockIndex->nHeight; + CreateRow(rowcount, true, bIsBuy, confirmations, txTimeStr.toStdString(), displayType, displayAddress, displayAmount, hash.GetHex(), true); + rowcount += 1; + } + } + if (0 == parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity { if (0<=mp_obj.step1()) { @@ -367,116 +387,78 @@ void TXHistoryDialog::UpdateHistory() (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_MANUAL)) { propertyId = _my_sps->findSPByTX(hash); + if (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_FIXED) + { amount = getTotalTokens(propertyId); } + else + { amount = 0; } } } divisible = isPropertyDivisible(propertyId); } } - } - QListWidgetItem *qItem = new QListWidgetItem(); - qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); - // shrink tx type - string displayType = "Unknown"; - switch (mp_obj.getType()) - { - case MSC_TYPE_SIMPLE_SEND: displayType = "Send"; break; - case MSC_TYPE_RESTRICTED_SEND: displayType = "Rest. Send"; break; - case MSC_TYPE_SEND_TO_OWNERS: displayType = "Send To Owners"; break; - case MSC_TYPE_SAVINGS_MARK: displayType = "Mark Savings"; break; - case MSC_TYPE_SAVINGS_COMPROMISED: ; displayType = "Lock Savings"; break; - case MSC_TYPE_RATELIMITED_MARK: displayType = "Rate Limit"; break; - case MSC_TYPE_AUTOMATIC_DISPENSARY: displayType = "Auto Dispense"; break; - case MSC_TYPE_TRADE_OFFER: displayType = "DEx Trade"; break; - case MSC_TYPE_METADEX: displayType = "MetaDEx Trade"; break; - case MSC_TYPE_ACCEPT_OFFER_BTC: displayType = "DEx Accept"; break; - case MSC_TYPE_CREATE_PROPERTY_FIXED: displayType = "Create Property"; break; - case MSC_TYPE_CREATE_PROPERTY_VARIABLE: displayType = "Create Property"; break; - case MSC_TYPE_PROMOTE_PROPERTY: displayType = "Promo Property"; - case MSC_TYPE_CLOSE_CROWDSALE: displayType = "Close Crowdsale"; - case MSC_TYPE_CREATE_PROPERTY_MANUAL: displayType = "Create Property"; break; - case MSC_TYPE_GRANT_PROPERTY_TOKENS: displayType = "Grant Tokens"; break; - case MSC_TYPE_REVOKE_PROPERTY_TOKENS: displayType = "Revoke Tokens"; break; - case MSC_TYPE_CHANGE_ISSUER_ADDRESS: displayType = "Change Issuer"; break; - } - - string displayAmount; - string displayToken; - string displayValid; - string displayAddress; - if (IsMyAddress(senderAddress)) { displayAddress = senderAddress; } else { displayAddress = refAddress; } - if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } - if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; } - if (propertyId < 3) - { - if(propertyId == 1) { displayToken = " MSC"; } - if(propertyId == 2) { displayToken = " TMSC"; } - } - else - { - string s = to_string(propertyId); - displayToken = " SPT#" + s; - } - string displayDirection = "out"; - if ((displayType == "Send") && (!IsMyAddress(senderAddress))) { displayType = "Receive"; } - - QDateTime txTime; - txTime.setTime_t(nTime); - QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); - if (IsMyAddress(senderAddress)) displayAmount = "-" + displayAmount; - // override/hide display amount for invalid creates, we can't display amount and property as no prop exists - if (!valid) - { + QListWidgetItem *qItem = new QListWidgetItem(); + qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex())); + bool fundsMoved = true; + // shrink tx type + string displayType = "Unknown"; + switch (mp_obj.getType()) + { + case MSC_TYPE_SIMPLE_SEND: displayType = "Send"; break; + case MSC_TYPE_RESTRICTED_SEND: displayType = "Rest. Send"; break; + case MSC_TYPE_SEND_TO_OWNERS: displayType = "Send To Owners"; break; + case MSC_TYPE_SAVINGS_MARK: displayType = "Mark Savings"; fundsMoved = false; break; + case MSC_TYPE_SAVINGS_COMPROMISED: ; displayType = "Lock Savings"; break; + case MSC_TYPE_RATELIMITED_MARK: displayType = "Rate Limit"; break; + case MSC_TYPE_AUTOMATIC_DISPENSARY: displayType = "Auto Dispense"; break; + case MSC_TYPE_TRADE_OFFER: displayType = "DEx Trade"; fundsMoved = false; break; + case MSC_TYPE_METADEX: displayType = "MetaDEx Trade"; fundsMoved = false; break; + case MSC_TYPE_ACCEPT_OFFER_BTC: displayType = "DEx Accept"; fundsMoved = false; break; + case MSC_TYPE_CREATE_PROPERTY_FIXED: displayType = "Create Property"; break; + case MSC_TYPE_CREATE_PROPERTY_VARIABLE: displayType = "Create Property"; break; + case MSC_TYPE_PROMOTE_PROPERTY: displayType = "Promo Property"; + case MSC_TYPE_CLOSE_CROWDSALE: displayType = "Close Crowdsale"; + case MSC_TYPE_CREATE_PROPERTY_MANUAL: displayType = "Create Property"; break; + case MSC_TYPE_GRANT_PROPERTY_TOKENS: displayType = "Grant Tokens"; break; + case MSC_TYPE_REVOKE_PROPERTY_TOKENS: displayType = "Revoke Tokens"; break; + case MSC_TYPE_CHANGE_ISSUER_ADDRESS: displayType = "Change Issuer"; fundsMoved = false; break; + } + if (IsMyAddress(senderAddress)) { displayAddress = senderAddress; } else { displayAddress = refAddress; } + if (divisible) { displayAmount = FormatDivisibleShortMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); } + if (propertyId < 3) + { + if(propertyId == 1) { displayAmount += " MSC"; } + if(propertyId == 2) { displayAmount += " TMSC"; } + } + else + { + string s = to_string(propertyId); + displayAmount += " SPT#" + s; + } + if ((displayType == "Send") && (!IsMyAddress(senderAddress))) { displayType = "Receive"; } + + QDateTime txTime; + txTime.setTime_t(nTime); + QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate); + bool inbound = true; + if (!valid) fundsMoved = false; // funds never move in invalid txs + // override/hide display amount for invalid creates and unknown transactions as we + // can't display amount and property as no prop exists if ((mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_FIXED) || (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_VARIABLE) || - (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_MANUAL)) + (mp_obj.getType() == MSC_TYPE_CREATE_PROPERTY_MANUAL) || + (displayType == "Unknown" )) { - displayAmount = "N/A"; + if (!valid) { displayAmount = "N/A"; } } + else + { + if ((fundsMoved) && (IsMyAddress(senderAddress))) + { displayAmount = "-" + displayAmount; inbound = false; } + } + int confirmations = 1 + chainHeight - pBlockIndex->nHeight; + CreateRow(rowcount, valid, inbound, confirmations, txTimeStr.toStdString(), displayType, displayAddress, displayAmount, hash.GetHex(), fundsMoved); + rowcount += 1; } - // icon - QIcon ic = QIcon(":/icons/transaction_0"); - int confirmations = 1 + chainHeight - pBlockIndex->nHeight; - switch(confirmations) - { - case 1: ic = QIcon(":/icons/transaction_1"); break; - case 2: ic = QIcon(":/icons/transaction_2"); break; - case 3: ic = QIcon(":/icons/transaction_3"); break; - case 4: ic = QIcon(":/icons/transaction_4"); break; - case 5: ic = QIcon(":/icons/transaction_5"); break; - } - if (confirmations > 5) ic = QIcon(":/icons/transaction_confirmed"); - if (!valid) ic = QIcon(":/icons/transaction_invalid"); - - // add to history - ui->txHistoryTable->setRowCount(rowcount+1); - QTableWidgetItem *dateCell = new QTableWidgetItem(txTimeStr); - QTableWidgetItem *typeCell = new QTableWidgetItem(QString::fromStdString(displayType)); - QTableWidgetItem *addressCell = new QTableWidgetItem(QString::fromStdString(displayAddress)); - QTableWidgetItem *amountCell = new QTableWidgetItem(QString::fromStdString(displayAmount + displayToken)); - QTableWidgetItem *iconCell = new QTableWidgetItem; - QTableWidgetItem *txidCell = new QTableWidgetItem(QString::fromStdString(hash.GetHex())); - iconCell->setIcon(ic); - addressCell->setTextAlignment(Qt::AlignLeft + Qt::AlignVCenter); - addressCell->setForeground(QColor("#707070")); - amountCell->setTextAlignment(Qt::AlignRight + Qt::AlignVCenter); - amountCell->setForeground(QColor("#00AA00")); - if (IsMyAddress(senderAddress)) amountCell->setForeground(QColor("#EE0000")); - if (rowcount % 2) - { - amountCell->setBackground(QColor("#F0F0F0")); - addressCell->setBackground(QColor("#F0F0F0")); - dateCell->setBackground(QColor("#F0F0F0")); - typeCell->setBackground(QColor("#F0F0F0")); - txidCell->setBackground(QColor("#F0F0F0")); - iconCell->setBackground(QColor("#F0F0F0")); - } - ui->txHistoryTable->setItem(rowcount, 0, iconCell); - ui->txHistoryTable->setItem(rowcount, 1, dateCell); - ui->txHistoryTable->setItem(rowcount, 2, typeCell); - ui->txHistoryTable->setItem(rowcount, 3, addressCell); - ui->txHistoryTable->setItem(rowcount, 4, amountCell); - ui->txHistoryTable->setItem(rowcount, 5, txidCell); - rowcount += 1; } } // don't burn time doing more work than we need to diff --git a/src/qt/txhistorydialog.h b/src/qt/txhistorydialog.h index 53db18e05c35d..99a8c81277896 100644 --- a/src/qt/txhistorydialog.h +++ b/src/qt/txhistorydialog.h @@ -33,6 +33,7 @@ class TXHistoryDialog : public QDialog //void FullRefresh(); explicit TXHistoryDialog(QWidget *parent = 0); void setModel(WalletModel *model); + void CreateRow(int rowcount, bool valid, bool bInbound, int confirmations, std::string txTimeStr, std::string displayType, std::string displayAddress, std::string displayAmount, std::string txidStr, bool fundsMoved); void accept(); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). */ From 7c85792a6dd0a799c39ba23cfca081308d48e143 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 14 Dec 2014 12:50:30 -0800 Subject: [PATCH 121/141] Fix duplicate element name --- src/qt/forms/overviewpage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index ca3b2001fdb34..8c03f3556855f 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -407,7 +407,7 @@ - + Qt::Horizontal From 75dfd85a361cd4ddf9136e95306a58a6c3c0a543 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Sun, 14 Dec 2014 12:52:37 -0800 Subject: [PATCH 122/141] Fix bad zorder attributes in lookupspdialog UI form --- src/qt/forms/lookupspdialog.ui | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/qt/forms/lookupspdialog.ui b/src/qt/forms/lookupspdialog.ui index 5270a059d9106..16cf238b4f449 100644 --- a/src/qt/forms/lookupspdialog.ui +++ b/src/qt/forms/lookupspdialog.ui @@ -341,9 +341,6 @@ - name - - From a4518e44ee846f713c2010e5cf5fef71d446925b Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 3 Feb 2015 16:05:03 -0800 Subject: [PATCH 123/141] Fix error relating to obtaining STO recipients from UI --- src/qt/txhistorydialog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 4f74e7f7952ff..0008115c7549d 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -286,7 +286,8 @@ void TXHistoryDialog::UpdateHistory() string displayAmount; Array receiveArray; uint64_t total = 0; - s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &total); // get matching receipts + uint64_t stoFee = 0; + s_stolistdb->getRecipients(hash, addressParam, &receiveArray, &total, &stoFee); // get matching receipts int confirmations = 1 + chainHeight - pBlkIdx->nHeight; if (divisible) { displayAmount = FormatDivisibleShortMP(total); } else { displayAmount = FormatIndivisibleMP(total); } if (propertyId < 3) { @@ -522,7 +523,8 @@ void TXHistoryDialog::showDetails() if (pos!=std::string::npos) { Array receiveArray; uint64_t tmpAmount = 0; - s_stolistdb->getRecipients(txid, "", &receiveArray, &tmpAmount); + uint64_t tmpSTOFee = 0; + s_stolistdb->getRecipients(txid, "", &receiveArray, &tmpAmount, &tmpSTOFee); txobj.push_back(Pair("recipients", receiveArray)); //rewrite string strTXText = write_string(Value(txobj), false) + "\n"; From 6c97976991b232b30f41feb7235a965d1e49ae67 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 3 Feb 2015 21:30:23 -0800 Subject: [PATCH 124/141] Redo splash screens to reflect new branding --- src/qt/res/images/splash.png | Bin 67321 -> 8243 bytes src/qt/res/images/splash_testnet.png | Bin 68808 -> 8248 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/qt/res/images/splash.png b/src/qt/res/images/splash.png index a6d04416740c3d600af72d7779d1c9dab5927da9..d11f9cfca0b99bb0e7c4236af6a8dd924eceb763 100644 GIT binary patch literal 8243 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 UTN=;E`}glwQ&mr;PRS1VU$dJvH~;_u literal 67321 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 literal 68808 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 Date: Tue, 3 Feb 2015 22:30:54 -0800 Subject: [PATCH 125/141] Redo splashscreen CPP to adjust layout to new splash --- src/qt/splashscreen.cpp | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 43e16268993d1..5614bcf4eadf3 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -26,20 +26,17 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest setAutoFillBackground(true); // set reference point, paddings - int paddingRight = 50; - int paddingTop = 50; - int titleVersionVSpace = 17; - int titleCopyrightVSpace = 40; - int titleCopyrightMSCVSpace = 17; + int paddingTop = 200; + int titleVersionVSpace = 40; + int titleCopyrightVSpace = 60; float fontFactor = 1.0; // define text to place string coreVersionStr = "Experimental UI 0.0." + boost::lexical_cast((double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE; - QString titleText = tr("Master Core"); + QString titleText = tr("Omni Core"); QString versionText = QString::fromStdString(coreVersionStr); - QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); - QString copyrightMSC = QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); + QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers, ")) + QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object QString font = "Arial"; @@ -65,26 +62,17 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest fontFactor = 0.75; } - pixPaint.setFont(QFont(font, 33*fontFactor)); - fm = pixPaint.fontMetrics(); - titleTextWidth = fm.width(titleText); - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight,paddingTop,titleText); - - pixPaint.setFont(QFont(font, 15*fontFactor)); - - // if the version string is to long, reduce size + // draw version + pixPaint.setFont(QFont(font, 20*fontFactor)); fm = pixPaint.fontMetrics(); int versionTextWidth = fm.width(versionText); - if(versionTextWidth > titleTextWidth+paddingRight-10) { - pixPaint.setFont(QFont(font, 10*fontFactor)); - titleVersionVSpace -= 5; - } - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText); + pixPaint.drawText((newPixmap.width()-versionTextWidth)/2,paddingTop+titleVersionVSpace,versionText); // draw copyright stuff pixPaint.setFont(QFont(font, 10*fontFactor)); - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleCopyrightVSpace,copyrightText); - pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleCopyrightVSpace+titleCopyrightMSCVSpace,copyrightMSC); + fm = pixPaint.fontMetrics(); + int copyrightTextWidth = fm.width(copyrightText); + pixPaint.drawText((newPixmap.width()-copyrightTextWidth)/2,paddingTop+titleCopyrightVSpace,copyrightText); // draw testnet string if testnet is on if(isTestNet) { From 748946b3863e7c998eb450278124e1c0b4b2ed0f Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 3 Feb 2015 22:36:26 -0800 Subject: [PATCH 126/141] Fix bad version display due to float --- src/mastercore_rpc.cpp | 2 +- src/qt/splashscreen.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index fcf137148b7fd..3fb9663022698 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -1922,7 +1922,7 @@ Value getinfo_MP(const Array& params, bool fHelp) // other bits of info we want to report should be included here // provide the mastercore and bitcoin version and if available commit id - infoResponse.push_back(Pair("mastercoreversion", "0.0." + boost::lexical_cast((double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE )); + infoResponse.push_back(Pair("mastercoreversion", "0.0." + strprintf("%.1f",(double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE )); infoResponse.push_back(Pair("bitcoincoreversion", "0." + boost::lexical_cast((int)CLIENT_VERSION/100))); infoResponse.push_back(Pair("commitinfo", COMMIT_INFO)); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 5614bcf4eadf3..489401d749937 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -33,7 +33,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest float fontFactor = 1.0; // define text to place - string coreVersionStr = "Experimental UI 0.0." + boost::lexical_cast((double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE; + string coreVersionStr = "Experimental UI 0.0." + strprintf("%.1f",(double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE; QString titleText = tr("Omni Core"); QString versionText = QString::fromStdString(coreVersionStr); QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers, ")) + QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); From 832eca1ac4450eef2e4dfcd33c143b78bd81e4be Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Tue, 3 Feb 2015 22:43:00 -0800 Subject: [PATCH 127/141] Change copyright year --- src/clientversion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clientversion.h b/src/clientversion.h index ef184d8e05620..56c0dc16c627f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -19,7 +19,7 @@ // Copyright year (2009-this) // Todo: update this when changing our copyright comments in the source -#define COPYRIGHT_YEAR 2014 +#define COPYRIGHT_YEAR 2015 #endif //HAVE_CONFIG_H From 93c47da1f323c1ea57f3fafe13bd532c80d95688 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 15:48:34 -0800 Subject: [PATCH 128/141] Update Omni labels --- src/qt/bitcoin.cpp | 4 ++-- src/qt/bitcoingui.cpp | 20 ++++++++++---------- src/qt/sendmpdialog.cpp | 4 ++-- src/qt/splashscreen.cpp | 2 +- src/qt/utilitydialog.cpp | 6 +++--- src/qt/walletview.cpp | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index f41a65b7f267f..eda653c8cecce 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -596,8 +596,8 @@ int main(int argc, char *argv[]) /// Show warning string strWarningText = "This software is EXPERIMENTAL software for TESTNET TRANSACTIONS only. USE ON MAINNET AT YOUR OWN RISK.\n\n"; strWarningText += "The protocol and transaction processing rules for Mastercoin are still under active development and are subject to change in future.\n\n"; - strWarningText += "Master Core should be considered an alpha-level product, and you use it at your own risk. Neither the Mastercoin Foundation nor the Master Core developers assumes any responsibility for funds misplaced, mishandled, lost, or misallocated.\n\n"; - strWarningText += "Further, please note that this installation of Master Core should be viewed as EXPERIMENTAL. Your wallet data may be lost, deleted, or corrupted, with or without warning due to bugs or glitches. Please take caution.\n\n"; + strWarningText += "Omni Core should be considered an alpha-level product, and you use it at your own risk. Neither the Omni Foundation nor the Omni Core developers assumes any responsibility for funds misplaced, mishandled, lost, or misallocated.\n\n"; + strWarningText += "Further, please note that this installation of Omni Core should be viewed as EXPERIMENTAL. Your wallet data may be lost, deleted, or corrupted, with or without warning due to bugs or glitches. Please take caution.\n\n"; strWarningText += "This software is provided open-source at no cost. You are responsible for knowing the law in your country and determining if your use of this software contravenes any local laws.\n\n"; strWarningText += "DO NOT use wallet(s) with any significant amount of any property/currency while testing!"; QString warningText = QString::fromStdString(strWarningText); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 70c6078e46ed8..eccf24ac26db4 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -72,7 +72,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : { GUIUtil::restoreWindowGeometry("nWindow", QSize(680, 650), this); - QString windowTitle = tr("Master Core") + " - "; + QString windowTitle = tr("Omni Core") + " - "; #ifdef ENABLE_WALLET /* if compiled with wallet support, -disablewallet can still disable the wallet */ bool enableWallet = !GetBoolArg("-disablewallet", false); @@ -227,14 +227,14 @@ void BitcoinGUI::createActions(bool fIsTestnet) tabGroup->addAction(overviewAction); balancesAction = new QAction(QIcon(":/icons/balances"), tr("&Balances"), this); - balancesAction->setStatusTip(tr("Show Master Protocol balances")); + balancesAction->setStatusTip(tr("Show Omni Protocol balances")); balancesAction->setToolTip(balancesAction->statusTip()); balancesAction->setCheckable(true); balancesAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(balancesAction); sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this); - sendCoinsAction->setStatusTip(tr("Send Master Protocol and Bitcoin transactions")); + sendCoinsAction->setStatusTip(tr("Send Omni Protocol and Bitcoin transactions")); sendCoinsAction->setToolTip(sendCoinsAction->statusTip()); sendCoinsAction->setCheckable(true); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); @@ -255,7 +255,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) // tabGroup->addAction(exchangeAction); smartPropertyAction = new QAction(QIcon(":/icons/smartproperty"), tr("Smart &Property"), this); - smartPropertyAction->setStatusTip(tr("Lookup and interact with Master Protocol Smart Properties")); + smartPropertyAction->setStatusTip(tr("Lookup and interact with Omni Protocol Smart Properties")); smartPropertyAction->setToolTip(smartPropertyAction->statusTip()); smartPropertyAction->setCheckable(true); smartPropertyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); @@ -269,7 +269,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) tabGroup->addAction(historyAction); toolboxAction = new QAction(QIcon(":/icons/toolbox"), tr("&Toolbox"), this); - toolboxAction->setStatusTip(tr("Tools to obtain varions Master Protocol information and transaction information")); + toolboxAction->setStatusTip(tr("Tools to obtain varions Omni Protocol information and transaction information")); toolboxAction->setToolTip(toolboxAction->statusTip()); toolboxAction->setCheckable(true); toolboxAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_8)); @@ -299,10 +299,10 @@ void BitcoinGUI::createActions(bool fIsTestnet) quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); quitAction->setMenuRole(QAction::QuitRole); if (!fIsTestnet) - aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Master Core"), this); + aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Omni Core"), this); else - aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Master Core"), this); - aboutAction->setStatusTip(tr("Show information about Master Core")); + aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Omni Core"), this); + aboutAction->setStatusTip(tr("Show information about Omni Core")); aboutAction->setMenuRole(QAction::AboutRole); #if QT_VERSION < 0x050000 aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this); @@ -511,12 +511,12 @@ void BitcoinGUI::createTrayIcon(bool fIsTestnet) if (!fIsTestnet) { - trayIcon->setToolTip(tr("Mastercore client")); + trayIcon->setToolTip(tr("Omnicore client")); trayIcon->setIcon(QIcon(":/icons/toolbar")); } else { - trayIcon->setToolTip(tr("Mastercore client") + " " + tr("[testnet]")); + trayIcon->setToolTip(tr("Omnicore client") + " " + tr("[testnet]")); trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); } diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index 6ea84012ccc90..2d88001d4c695 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -79,7 +79,7 @@ SendMPDialog::SendMPDialog(QWidget *parent) : #endif // populate placeholder text - ui->sendToLineEdit->setPlaceholderText("Enter a Master Protocol address (e.g. 1MaSTeRPRotocolADDreSShef77z6A5S4P)"); + ui->sendToLineEdit->setPlaceholderText("Enter a Omni Protocol address (e.g. 1oMn1PRotocolADDreSShef77z6A5S4P)"); ui->amountLineEdit->setPlaceholderText("Enter Amount"); // connect actions @@ -411,7 +411,7 @@ void SendMPDialog::sendMPTransaction() updateBalances(); // display the result - string strSentText = "Your Master Protocol transaction has been sent.\n\nThe transaction ID is:\n\n"; + string strSentText = "Your Omni Protocol transaction has been sent.\n\nThe transaction ID is:\n\n"; strSentText += sendTXID.GetHex() + "\n\n"; QString sentText = QString::fromStdString(strSentText); QMessageBox sentDialog; diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 489401d749937..a8e953eb5dc81 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -36,7 +36,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest string coreVersionStr = "Experimental UI 0.0." + strprintf("%.1f",(double)OMNICORE_VERSION_BASE/10) + OMNICORE_VERSION_TYPE; QString titleText = tr("Omni Core"); QString versionText = QString::fromStdString(coreVersionStr); - QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers, ")) + QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Master Protocol developers")); + QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers, ")) + QChar(0xA9)+QString(" 2013-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Omni Protocol developers")); QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object QString font = "Arial"; diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index a8a6a7ae484f7..d8e2ad442f8df 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -29,7 +29,7 @@ AboutDialog::AboutDialog(QWidget *parent) : // Set current copyright year ui->copyrightLabel->setText(tr("Copyright") + QString(" (C) 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers")); - ui->copyrightLabel_MC->setText(tr("Copyright") + QString(" (C) 2013-%1 ").arg(COPYRIGHT_YEAR) + tr("The Master Core developers")); + ui->copyrightLabel_MC->setText(tr("Copyright") + QString(" (C) 2013-%1 ").arg(COPYRIGHT_YEAR) + tr("The Omni Core developers")); } void AboutDialog::setModel(ClientModel *model) @@ -67,7 +67,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent) : ui->setupUi(this); GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this); - header = tr("Master Core") + " " + tr("version") + " " + + header = tr("Omni Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()) + "\n\n" + tr("Usage:") + "\n" + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; @@ -127,7 +127,7 @@ void ShutdownWindow::showShutdownWindow(BitcoinGUI *window) QWidget *shutdownWindow = new QWidget(); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(new QLabel( - tr("Master Core is shutting down...") + "

" + + tr("Omni Core is shutting down...") + "

" + tr("Do not shut down the computer until this window disappears."))); shutdownWindow->setLayout(layout); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 771c3770fc754..9a58bacdde5ca 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -87,7 +87,7 @@ WalletView::WalletView(QWidget *parent): transactionsPage = new QWidget(this); QVBoxLayout *txvbox = new QVBoxLayout(); QTabWidget *txTabHolder = new QTabWidget(); - txTabHolder->addTab(mpTXTab,tr("Master Protocol")); + txTabHolder->addTab(mpTXTab,tr("Omni Protocol")); txTabHolder->addTab(bitcoinTXTab,tr("Bitcoin")); txvbox->addWidget(txTabHolder); transactionsPage->setLayout(txvbox); @@ -101,7 +101,7 @@ WalletView::WalletView(QWidget *parent): sendCoinsTab = new SendCoinsDialog(); sendMPTab = new SendMPDialog(); QTabWidget *tabHolder = new QTabWidget(); - tabHolder->addTab(sendMPTab,tr("Master Protocol")); + tabHolder->addTab(sendMPTab,tr("Omni Protocol")); tabHolder->addTab(sendCoinsTab,tr("Bitcoin")); svbox->addWidget(tabHolder); sendCoinsPage->setLayout(svbox); From 9613fdbfb253a97cae70ce81537c7b28bb210f9a Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 15:50:14 -0800 Subject: [PATCH 129/141] Add missing breaks as noticed by DexX --- src/qt/txhistorydialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 0008115c7549d..5cb1be30ac333 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -416,8 +416,8 @@ void TXHistoryDialog::UpdateHistory() case MSC_TYPE_ACCEPT_OFFER_BTC: displayType = "DEx Accept"; fundsMoved = false; break; case MSC_TYPE_CREATE_PROPERTY_FIXED: displayType = "Create Property"; break; case MSC_TYPE_CREATE_PROPERTY_VARIABLE: displayType = "Create Property"; break; - case MSC_TYPE_PROMOTE_PROPERTY: displayType = "Promo Property"; - case MSC_TYPE_CLOSE_CROWDSALE: displayType = "Close Crowdsale"; + case MSC_TYPE_PROMOTE_PROPERTY: displayType = "Promo Property"; break; + case MSC_TYPE_CLOSE_CROWDSALE: displayType = "Close Crowdsale"; break; case MSC_TYPE_CREATE_PROPERTY_MANUAL: displayType = "Create Property"; break; case MSC_TYPE_GRANT_PROPERTY_TOKENS: displayType = "Grant Tokens"; break; case MSC_TYPE_REVOKE_PROPERTY_TOKENS: displayType = "Revoke Tokens"; break; From b9e03c0f02bd7ebbd9b02d08ff2b83673e4147fa Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 15:53:37 -0800 Subject: [PATCH 130/141] Change wording to more accurately msg on tx lookup --- src/qt/lookuptxdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/lookuptxdialog.cpp b/src/qt/lookuptxdialog.cpp index 16cc53e4f55cf..c159d7969bc3d 100644 --- a/src/qt/lookuptxdialog.cpp +++ b/src/qt/lookuptxdialog.cpp @@ -159,7 +159,7 @@ void LookupTXDialog::searchTX() else { // show error message - string strText = "The transaction ID entered was not valid."; + string strText = "The transaction ID entered is either not valid Omni transaction or has not yet been confirmed."; QString strQText = QString::fromStdString(strText); QMessageBox errorDialog; errorDialog.setIcon(QMessageBox::Critical); From 5d7301b62f8561130ade5a85e410a6739587e685 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 16:14:12 -0800 Subject: [PATCH 131/141] Fix ecosystem display on property lookup --- src/qt/lookupspdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/lookupspdialog.cpp b/src/qt/lookupspdialog.cpp index a3b70a32af21c..bc09b20d9887e 100644 --- a/src/qt/lookupspdialog.cpp +++ b/src/qt/lookupspdialog.cpp @@ -254,7 +254,7 @@ void LookupSPDialog::updateDisplayedProperty() // populate the fields bool divisible=sp.isDivisible(); if (divisible) { ui->divisibleLabel->setText("Yes"); } else { ui->divisibleLabel->setText("No"); } - if (propertyId>2147483647) { ui->ecosystemLabel->setText("Test"); } else { ui->ecosystemLabel->setText("Production"); } + if (isTestEcosystemProperty(propertyId)) { ui->ecosystemLabel->setText("Test"); } else { ui->ecosystemLabel->setText("Production"); } ui->propertyIDLabel->setText(QString::fromStdString(FormatIndivisibleMP(propertyId))); ui->nameLabel->setText(QString::fromStdString(sp.name)); ui->categoryLabel->setText(QString::fromStdString(sp.category + " > " + sp.subcategory)); From e676287041b6e85ddbbe5cfa7b148af3b9c7a07c Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 16:20:09 -0800 Subject: [PATCH 132/141] Remove duplicate getsto_MP entry --- src/rpcserver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index e6a11ac042706..1a69b4c5691d9 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -330,7 +330,6 @@ static const CRPCCommand vRPCCommands[] = { "getactivecrowdsales_MP", &getactivecrowdsales_MP, false, false, true }, #if 0 { "trade_MP", &trade_MP, false, false, true }, - { "getsto_MP", &getsto_MP, false, false, true }, { "getorderbook_MP", &getorderbook_MP, false, false, true }, { "gettradessince_MP", &gettradessince_MP, false, false, true }, { "getopenorders_MP", &getopenorders_MP, false, false, true }, From fd212f3f8b494aa6bd25b3e29e22e701b6c94b3b Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 16:23:03 -0800 Subject: [PATCH 133/141] Remove unneeeded includes after moving to strprintf --- src/qt/splashscreen.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index a8e953eb5dc81..7a0ab4bfdd0e8 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -14,10 +14,6 @@ #include #include #include -#include -#include "mastercore_version.h" - -#include #include "mastercore_version.h" SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet) : From 0998a25681e4dcbd153a9ca9ca138a85d4695e09 Mon Sep 17 00:00:00 2001 From: zathras-crypto Date: Thu, 5 Feb 2015 16:24:26 -0800 Subject: [PATCH 134/141] Remove debug line no longer used --- src/mastercore.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 322e5a4ed16f5..096e73ef23a4c 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -120,7 +120,6 @@ const int msc_debug_persistence = 0; int msc_debug_metadex1= 0; int msc_debug_metadex2= 0; int msc_debug_metadex3= 0; // enable this to see the orderbook before & after each TX -int msc_debug_ui = 1; const static int disable_Divs = 0; const static int disableLevelDB = 0; From 3d4e4c9b7adad2cae1c07d85544dc83eb5239820 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 6 Feb 2015 06:15:22 +0100 Subject: [PATCH 135/141] Fix: Missing LOCK of cs_main in selectCoins() Can result in a failed LOCK otherwise: Assertion failed: lock cs_main not held in main.cpp:596; locks held: wallet->cs_wallet mastercore.cpp:2718 See: https://github.com/mastercoin-MSC/mastercore/pull/243#issuecomment-73003976 --- src/mastercore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 096e73ef23a4c..c727e96e26b04 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -2714,7 +2714,7 @@ static int64_t selectCoins(const string &FromAddress, CCoinControl &coinControl, // if referenceamount is set it is needed to be accounted for here too if (0 < additional) n_max += additional; - LOCK(wallet->cs_wallet); + LOCK2(cs_main, wallet->cs_wallet); string sAddress = ""; From bfb83fe239a8503953ff359e2b2050407459702b Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 6 Feb 2015 06:18:03 +0100 Subject: [PATCH 136/141] QT: Remove forceUpdateBalances() in WalletModel() It's no longer used and can be removed. --- src/qt/walletmodel.cpp | 39 --------------------------------------- src/qt/walletmodel.h | 1 - 2 files changed, 40 deletions(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e64cf1e70389a..39244c4736237 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -42,12 +42,6 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); pollTimer->start(MODEL_UPDATE_DELAY); - // The above timer is too fast for MasterCore usage, we'll have a new one here - /* - updateTimer = new QTimer(this); - connect(updateTimer, SIGNAL(timeout()), this, SLOT(forceUpdateBalances())); - updateTimer->start(MASTERCORE_UPDATE_DELAY); - */ subscribeToCoreSignals(); } @@ -102,38 +96,6 @@ void WalletModel::updateStatus() emit encryptionStatusChanged(newEncryptionStatus); } -void WalletModel::forceUpdateBalances() -{ - // boost::timer t; - // Get required locks upfront. This avoids the GUI from getting stuck on - // periodical polls if the core is holding the locks for a longer time - - // for example, during a wallet rescan. - TRY_LOCK(cs_main, lockMain); - if(!lockMain) - return; - TRY_LOCK(wallet->cs_wallet, lockWallet); - if(!lockWallet) - return; - - qint64 newBalance = getBalance(); - qint64 newUnconfirmedBalance = getUnconfirmedBalance(); - qint64 newImmatureBalance = getImmatureBalance(); - - if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) - { - cachedBalance = newBalance; - cachedUnconfirmedBalance = newUnconfirmedBalance; - cachedImmatureBalance = newImmatureBalance; - } - - // force everything to be updated - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); - if(transactionTableModel) transactionTableModel->updateConfirmations(); - /* printf("DEBUG: forceUpdate took"); - std::cout << t.elapsed() << std::endl; - printf("\n"); */ -} - void WalletModel::pollBalanceChanged() { // Get required locks upfront. This avoids the GUI from getting stuck on @@ -152,7 +114,6 @@ void WalletModel::pollBalanceChanged() cachedNumBlocks = chainActive.Height(); checkBalanceChanged(); - forceUpdateBalances(); if(transactionTableModel) transactionTableModel->updateConfirmations(); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index a6786a1e12e65..b34ccdcb6b751 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -250,7 +250,6 @@ public slots: void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status); /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ void pollBalanceChanged(); - void forceUpdateBalances(); }; #endif // WALLETMODEL_H From 671e51ff717e69aba982bfd90e756efdb72569d6 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 6 Feb 2015 06:31:33 +0100 Subject: [PATCH 137/141] QT: Refine updates of "Send" dialog --- src/qt/sendmpdialog.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index 2d88001d4c695..b288117d2a4ee 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -89,9 +89,7 @@ SendMPDialog::SendMPDialog(QWidget *parent) : connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendButtonClicked())); // initial update - updatePropSelector(); - updateProperty(); - updateFrom(); + balancesUpdated(); } void SendMPDialog::setModel(WalletModel *model) @@ -102,7 +100,6 @@ void SendMPDialog::setModel(WalletModel *model) void SendMPDialog::updatePropSelector() { - //printf("sendmpdialog::updatePropSelector()\n"); QString spId = ui->propertyComboBox->itemData(ui->propertyComboBox->currentIndex()).toString(); ui->propertyComboBox->clear(); for (unsigned int propertyId = 1; propertyId<100000; propertyId++) @@ -143,10 +140,6 @@ void SendMPDialog::clearFields() void SendMPDialog::updateFrom() { - // update wallet balances - set_wallet_totals(); - updateBalances(); - // check if this from address has sufficient fees for a send, if not light up warning label QString selectedFromAddress = ui->sendFromComboBox->currentText(); int64_t inputTotal = feeCheck(selectedFromAddress.toStdString()); @@ -164,9 +157,6 @@ void SendMPDialog::updateFrom() void SendMPDialog::updateProperty() { - // update wallet balances - set_wallet_totals(); - // get currently selected from address QString currentSetFromAddress = ui->sendFromComboBox->currentText(); @@ -206,7 +196,6 @@ void SendMPDialog::updateProperty() { ui->amountLineEdit->setPlaceholderText("Enter Indivisible Amount"); } - updateBalances(); } void SendMPDialog::updateBalances() @@ -433,12 +422,15 @@ void SendMPDialog::sendMPTransaction() void SendMPDialog::sendFromComboBoxChanged(int idx) { + updateBalances(); updateFrom(); } void SendMPDialog::propertyComboBoxChanged(int idx) { updateProperty(); + updateBalances(); + updateFrom(); } void SendMPDialog::clearButtonClicked() @@ -453,6 +445,10 @@ void SendMPDialog::sendButtonClicked() void SendMPDialog::balancesUpdated() { + set_wallet_totals(); + updatePropSelector(); + updateProperty(); updateBalances(); + updateFrom(); } From 86ed32baef9565ded811abda81a792bcb765a24d Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 6 Feb 2015 07:53:07 +0100 Subject: [PATCH 138/141] QT: In "Overview" unhide "Smart Properties" on update --- src/qt/overviewpage.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 1d3e077873019..6d09f47906365 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -281,11 +281,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 balText += tokenLabel; ui->SPbal1->setText(balText.c_str()); } + ui->SPname1->setVisible(true); + ui->SPbal1->setVisible(true); } else { - ui->SPname1->setText("N/A"); - ui->SPbal1->setText("N/A"); ui->SPname1->setVisible(false); ui->SPbal1->setVisible(false); } @@ -302,11 +302,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 balText += " SPT"; ui->SPbal2->setText(balText.c_str()); } + ui->SPname2->setVisible(true); + ui->SPbal2->setVisible(true); } else { - ui->SPname2->setText("N/A"); - ui->SPbal2->setText("N/A"); ui->SPname2->setVisible(false); ui->SPbal2->setVisible(false); } @@ -323,11 +323,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 balText += " SPT"; ui->SPbal3->setText(balText.c_str()); } + ui->SPname3->setVisible(true); + ui->SPbal3->setVisible(true); } else { - ui->SPname3->setText("N/A"); - ui->SPbal3->setText("N/A"); ui->SPname3->setVisible(false); ui->SPbal3->setVisible(false); } @@ -344,11 +344,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 balText += " SPT"; ui->SPbal4->setText(balText.c_str()); } + ui->SPname4->setVisible(true); + ui->SPbal4->setVisible(true); } else { - ui->SPname4->setText("N/A"); - ui->SPbal4->setText("N/A"); ui->SPname4->setVisible(false); ui->SPbal4->setVisible(false); } @@ -365,11 +365,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 balText += " SPT"; ui->SPbal5->setText(balText.c_str()); } + ui->SPname5->setVisible(true); + ui->SPbal5->setVisible(true); } else { - ui->SPname5->setText("N/A"); - ui->SPbal5->setText("N/A"); ui->SPname5->setVisible(false); ui->SPbal5->setVisible(false); } From f30a845ba776f6b325b4108edad31061618e97f4 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 6 Feb 2015 08:36:44 +0100 Subject: [PATCH 139/141] QT: in "Overview" align BTC and MSC amounts Before: http://i.imgur.com/2qv7bxf.png After: http://i.imgur.com/Y7S3CCb.png --- src/qt/forms/overviewpage.ui | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index 8c03f3556855f..899c14dc6a4ff 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -7,7 +7,7 @@ 0 0 664 - 440 + 447 @@ -406,21 +406,21 @@ - - + + Qt::Horizontal - + Total: - + @@ -445,6 +445,22 @@ + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 3 + + + + From f2055a24197f73a92c1d7b11df7a4d8f4cb7fde9 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Fri, 26 Dec 2014 23:14:28 +0100 Subject: [PATCH 140/141] QT: Guard against setPlaceholderText < QT 4.7 --- src/qt/lookupaddressdialog.cpp | 2 ++ src/qt/lookuptxdialog.cpp | 2 ++ src/qt/sendmpdialog.cpp | 12 ++++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/qt/lookupaddressdialog.cpp b/src/qt/lookupaddressdialog.cpp index e01c2093d133e..07735317a6580 100644 --- a/src/qt/lookupaddressdialog.cpp +++ b/src/qt/lookupaddressdialog.cpp @@ -145,8 +145,10 @@ LookupAddressDialog::LookupAddressDialog(QWidget *parent) : ui->setupUi(this); this->model = model; +#if QT_VERSION >= 0x040700 // populate placeholder text ui->searchLineEdit->setPlaceholderText("Search address"); +#endif // connect actions connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); diff --git a/src/qt/lookuptxdialog.cpp b/src/qt/lookuptxdialog.cpp index c159d7969bc3d..2c735d2310211 100644 --- a/src/qt/lookuptxdialog.cpp +++ b/src/qt/lookuptxdialog.cpp @@ -78,8 +78,10 @@ LookupTXDialog::LookupTXDialog(QWidget *parent) : ui->setupUi(this); this->model = model; +#if QT_VERSION >= 0x040700 // populate placeholder text ui->searchLineEdit->setPlaceholderText("Search transaction"); +#endif // connect actions connect(ui->searchButton, SIGNAL(clicked()), this, SLOT(searchButtonClicked())); diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index b288117d2a4ee..3f25d73464ed3 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -77,10 +77,11 @@ SendMPDialog::SendMPDialog(QWidget *parent) : ui->clearButton->setIcon(QIcon()); ui->sendButton->setIcon(QIcon()); #endif - +#if QT_VERSION >= 0x040700 // populate placeholder text ui->sendToLineEdit->setPlaceholderText("Enter a Omni Protocol address (e.g. 1oMn1PRotocolADDreSShef77z6A5S4P)"); ui->amountLineEdit->setPlaceholderText("Enter Amount"); +#endif // connect actions connect(ui->propertyComboBox, SIGNAL(activated(int)), this, SLOT(propertyComboBoxChanged(int))); @@ -187,15 +188,14 @@ void SendMPDialog::updateProperty() int fromIdx = ui->sendFromComboBox->findText(currentSetFromAddress); if (fromIdx != -1) { ui->sendFromComboBox->setCurrentIndex(fromIdx); } // -1 means the currently set from address doesn't have a balance in the newly selected property +#if QT_VERSION >= 0x040700 // update placeholder text - if (isPropertyDivisible(propertyId)) - { + if (isPropertyDivisible(propertyId)) { ui->amountLineEdit->setPlaceholderText("Enter Divisible Amount"); - } - else - { + } else { ui->amountLineEdit->setPlaceholderText("Enter Indivisible Amount"); } +#endif } void SendMPDialog::updateBalances() From 6e55b7442a15f6942b0a46f724a558805d4a1fb2 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Sat, 7 Feb 2015 15:21:16 +0100 Subject: [PATCH 141/141] QT: Guard against interface change of QHeaderView See: http://doc.qt.io/qt-5/sourcebreaks.html --- src/qt/txhistorydialog.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qt/txhistorydialog.cpp b/src/qt/txhistorydialog.cpp index 5cb1be30ac333..f40f314f3eb04 100644 --- a/src/qt/txhistorydialog.cpp +++ b/src/qt/txhistorydialog.cpp @@ -80,13 +80,18 @@ TXHistoryDialog::TXHistoryDialog(QWidget *parent) : ui->txHistoryTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Type")); ui->txHistoryTable->setHorizontalHeaderItem(3, new QTableWidgetItem("Address")); ui->txHistoryTable->setHorizontalHeaderItem(4, new QTableWidgetItem("Amount")); +#if QT_VERSION < 0x050000 + ui->txHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); +// ui->txHistoryTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); +#else + ui->txHistoryTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); +// ui->txHistoryTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); +#endif +// ui->txHistoryTable->setShowGrid(false); ui->txHistoryTable->verticalHeader()->setVisible(false); -// ui->txHistoryTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); -// ui->txHistoryTable->setShowGrid(false); ui->txHistoryTable->setSelectionBehavior(QAbstractItemView::SelectRows); ui->txHistoryTable->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->txHistoryTable->setSelectionMode(QAbstractItemView::SingleSelection); - ui->txHistoryTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch); ui->txHistoryTable->setColumnWidth(0, 23); ui->txHistoryTable->setColumnWidth(1, 150); ui->txHistoryTable->setColumnWidth(2, 130);