diff options
Diffstat (limited to 'src/qt')
56 files changed, 2368 insertions, 1569 deletions
diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 248dcba0ec..4ecd5629ea 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -34,7 +34,8 @@ QT_TS = locale/bitcoin_ach.ts locale/bitcoin_af_ZA.ts locale/bitcoin_ar.ts \ QT_FORMS_UI = forms/aboutdialog.ui forms/addressbookpage.ui \ forms/askpassphrasedialog.ui forms/editaddressdialog.ui forms/intro.ui \ - forms/optionsdialog.ui forms/overviewpage.ui forms/qrcodedialog.ui \ + forms/optionsdialog.ui forms/overviewpage.ui forms/receiverequestdialog.ui \ + forms/receivecoinsdialog.ui \ forms/rpcconsole.ui forms/sendcoinsdialog.ui forms/sendcoinsentry.ui \ forms/signverifymessagedialog.ui forms/transactiondescdialog.ui @@ -46,15 +47,15 @@ QT_MOC_CPP = moc_aboutdialog.cpp moc_addressbookpage.cpp \ moc_intro.cpp moc_macdockiconhandler.cpp moc_macnotificationhandler.cpp \ moc_monitoreddatamapper.cpp moc_notificator.cpp moc_optionsdialog.cpp \ moc_optionsmodel.cpp moc_overviewpage.cpp moc_paymentserver.cpp \ - moc_qrcodedialog.cpp moc_qvalidatedlineedit.cpp moc_qvaluecombobox.cpp \ + moc_receiverequestdialog.cpp moc_qvalidatedlineedit.cpp moc_qvaluecombobox.cpp \ + moc_receivecoinsdialog.cpp \ moc_rpcconsole.cpp moc_sendcoinsdialog.cpp moc_sendcoinsentry.cpp \ - moc_signverifymessagedialog.cpp moc_splashscreen.cpp moc_transactiondesc.cpp \ + moc_signverifymessagedialog.cpp moc_splashscreen.cpp moc_trafficgraphwidget.cpp moc_transactiondesc.cpp \ moc_transactiondescdialog.cpp moc_transactionfilterproxy.cpp \ moc_transactiontablemodel.cpp moc_transactionview.cpp moc_walletframe.cpp \ - moc_walletmodel.cpp moc_walletstack.cpp moc_walletview.cpp + moc_walletmodel.cpp moc_walletview.cpp BITCOIN_MM = macdockiconhandler.mm macnotificationhandler.mm -QR_CPP = qrcodedialog.cpp QT_MOC = intro.moc overviewpage.moc rpcconsole.moc @@ -71,11 +72,12 @@ BITCOIN_QT_H = aboutdialog.h addressbookpage.h addresstablemodel.h \ editaddressdialog.h guiconstants.h guiutil.h intro.h macdockiconhandler.h \ macnotificationhandler.h monitoreddatamapper.h notificator.h optionsdialog.h \ optionsmodel.h overviewpage.h paymentrequestplus.h paymentserver.h \ - qrcodedialog.h qvalidatedlineedit.h qvaluecombobox.h rpcconsole.h \ + receivecoinsdialog.h \ + receiverequestdialog.h qvalidatedlineedit.h qvaluecombobox.h rpcconsole.h \ sendcoinsdialog.h sendcoinsentry.h signverifymessagedialog.h splashscreen.h \ - transactiondescdialog.h transactiondesc.h transactionfilterproxy.h \ + trafficgraphwidget.h transactiondescdialog.h transactiondesc.h transactionfilterproxy.h \ transactionrecord.h transactiontablemodel.h transactionview.h walletframe.h \ - walletmodel.h walletmodeltransaction.h walletstack.h walletview.h + walletmodel.h walletmodeltransaction.h walletview.h RES_ICONS = res/icons/bitcoin.png res/icons/address-book.png \ res/icons/quit.png res/icons/send.png res/icons/toolbar.png \ @@ -101,11 +103,12 @@ BITCOIN_QT_CPP = aboutdialog.cpp addressbookpage.cpp \ guiutil.cpp intro.cpp monitoreddatamapper.cpp notificator.cpp \ optionsdialog.cpp optionsmodel.cpp overviewpage.cpp paymentrequestplus.cpp \ paymentserver.cpp qvalidatedlineedit.cpp qvaluecombobox.cpp \ + receivecoinsdialog.cpp receiverequestdialog.cpp \ rpcconsole.cpp sendcoinsdialog.cpp sendcoinsentry.cpp \ - signverifymessagedialog.cpp splashscreen.cpp transactiondesc.cpp \ + signverifymessagedialog.cpp splashscreen.cpp trafficgraphwidget.cpp transactiondesc.cpp \ transactiondescdialog.cpp transactionfilterproxy.cpp transactionrecord.cpp \ transactiontablemodel.cpp transactionview.cpp walletframe.cpp \ - walletmodel.cpp walletmodeltransaction.cpp walletstack.cpp walletview.cpp + walletmodel.cpp walletmodeltransaction.cpp walletview.cpp RES_IMAGES = res/images/about.png res/images/splash.png \ res/images/splash_testnet.png @@ -135,9 +138,6 @@ endif if TARGET_WINDOWS libbitcoinqt_a_SOURCES += $(BITCOIN_RC) endif -if USE_QRCODE - libbitcoinqt_a_SOURCES += $(QR_CPP) -endif # # bitcoin-qt binary # @@ -159,7 +159,7 @@ QT_QM=$(QT_TS:.ts=.qm) bitcoinstrings.cpp: FORCE $(MAKE) -C $(top_srcdir)/src qt/bitcoinstrings.cpp -translate: bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) $(QR_CPP) +translate: bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" @$(LUPDATE) $^ -locations relative -no-obsolete -ts locale/bitcoin_en.ts diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 5b8d44481e..ba5de4660a 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -12,10 +12,6 @@ #include "csvmodelwriter.h" #include "guiutil.h" -#ifdef USE_QRCODE -#include "qrcodedialog.h" -#endif - #include <QSortFilterProxyModel> #include <QClipboard> #include <QMessageBox> @@ -35,25 +31,29 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : ui->newAddress->setIcon(QIcon()); ui->copyAddress->setIcon(QIcon()); ui->deleteAddress->setIcon(QIcon()); - ui->verifyMessage->setIcon(QIcon()); - ui->signMessage->setIcon(QIcon()); ui->exportButton->setIcon(QIcon()); #endif -#ifndef USE_QRCODE - ui->showQRCode->setVisible(false); -#endif - switch(mode) { - case ForSending: + case ForSelection: + switch(tab) + { + case SendingTab: setWindowTitle(tr("Choose the address to send coins to")); break; + case ReceivingTab: setWindowTitle(tr("Choose the address to receive coins with")); break; + } connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept())); ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableView->setFocus(); + ui->closeButton->setText(tr("C&hoose")); ui->exportButton->hide(); break; case ForEditing: - ui->buttonBox->setVisible(false); + switch(tab) + { + case SendingTab: setWindowTitle(tr("Sending addresses")); break; + case ReceivingTab: setWindowTitle(tr("Receiving addresses")); break; + } break; } switch(tab) @@ -61,23 +61,17 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : case SendingTab: ui->labelExplanation->setText(tr("These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.")); ui->deleteAddress->setVisible(true); - ui->signMessage->setVisible(false); break; case ReceivingTab: - ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.")); + ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.")); ui->deleteAddress->setVisible(false); - ui->signMessage->setVisible(true); break; } // Context menu actions - QAction *copyAddressAction = new QAction(ui->copyAddress->text(), this); + QAction *copyAddressAction = new QAction(tr("&Copy Address"), this); QAction *copyLabelAction = new QAction(tr("Copy &Label"), this); QAction *editAction = new QAction(tr("&Edit"), this); - QAction *sendCoinsAction = new QAction(tr("Send &Coins"), this); - QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this); - QAction *signMessageAction = new QAction(ui->signMessage->text(), this); - QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this); deleteAction = new QAction(ui->deleteAddress->text(), this); // Build context menu @@ -88,30 +82,16 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : if(tab == SendingTab) contextMenu->addAction(deleteAction); contextMenu->addSeparator(); - if(tab == SendingTab) - contextMenu->addAction(sendCoinsAction); -#ifdef USE_QRCODE - contextMenu->addAction(showQRCodeAction); -#endif - if(tab == ReceivingTab) - contextMenu->addAction(signMessageAction); - else if(tab == SendingTab) - contextMenu->addAction(verifyMessageAction); // Connect signals for context menu actions connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyAddress_clicked())); connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction())); connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction())); connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteAddress_clicked())); - connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(onSendCoinsAction())); - connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked())); - connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked())); - connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked())); connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); - // Pass through accept action from button box - connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(accept())); } AddressBookPage::~AddressBookPage() @@ -197,42 +177,6 @@ void AddressBookPage::onEditAction() dlg.exec(); } -void AddressBookPage::on_signMessage_clicked() -{ - QTableView *table = ui->tableView; - QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - - foreach (QModelIndex index, indexes) - { - QString address = index.data().toString(); - emit signMessage(address); - } -} - -void AddressBookPage::on_verifyMessage_clicked() -{ - QTableView *table = ui->tableView; - QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - - foreach (QModelIndex index, indexes) - { - QString address = index.data().toString(); - emit verifyMessage(address); - } -} - -void AddressBookPage::onSendCoinsAction() -{ - QTableView *table = ui->tableView; - QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - - foreach (QModelIndex index, indexes) - { - QString address = index.data().toString(); - emit sendCoins(address); - } -} - void AddressBookPage::on_newAddress_clicked() { if(!model) @@ -278,32 +222,20 @@ void AddressBookPage::selectionChanged() ui->deleteAddress->setEnabled(true); ui->deleteAddress->setVisible(true); deleteAction->setEnabled(true); - ui->signMessage->setEnabled(false); - ui->signMessage->setVisible(false); - ui->verifyMessage->setEnabled(true); - ui->verifyMessage->setVisible(true); break; case ReceivingTab: // Deleting receiving addresses, however, is not allowed ui->deleteAddress->setEnabled(false); ui->deleteAddress->setVisible(false); deleteAction->setEnabled(false); - ui->signMessage->setEnabled(true); - ui->signMessage->setVisible(true); - ui->verifyMessage->setEnabled(false); - ui->verifyMessage->setVisible(false); break; } ui->copyAddress->setEnabled(true); - ui->showQRCode->setEnabled(true); } else { ui->deleteAddress->setEnabled(false); - ui->showQRCode->setEnabled(false); ui->copyAddress->setEnabled(false); - ui->signMessage->setEnabled(false); - ui->verifyMessage->setEnabled(false); } } @@ -312,9 +244,6 @@ void AddressBookPage::done(int retval) QTableView *table = ui->tableView; if(!table->selectionModel() || !table->model()) return; - // When this is a tab/widget and not a model dialog, ignore "done" - if(mode == ForEditing) - return; // Figure out which address was selected, and return it QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); @@ -339,7 +268,7 @@ void AddressBookPage::on_exportButton_clicked() // CSV is currently the only supported format QString filename = GUIUtil::getSaveFileName( this, - tr("Export Address Book Data"), QString(), + tr("Export Address List"), QString(), tr("Comma separated file (*.csv)")); if (filename.isNull()) return; @@ -358,25 +287,6 @@ void AddressBookPage::on_exportButton_clicked() } } -void AddressBookPage::on_showQRCode_clicked() -{ -#ifdef USE_QRCODE - QTableView *table = ui->tableView; - QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - - foreach (QModelIndex index, indexes) - { - QString address = index.data().toString(); - QString label = index.sibling(index.row(), 0).data(Qt::EditRole).toString(); - - QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this); - dialog->setModel(optionsModel); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); - } -#endif -} - void AddressBookPage::contextualMenu(const QPoint &point) { QModelIndex index = ui->tableView->indexAt(point); diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 34465aa65f..9255e58144 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -30,7 +30,7 @@ public: }; enum Mode { - ForSending, /**< Open address book to pick address for sending */ + ForSelection, /**< Open address book to pick address */ ForEditing /**< Open address book for editing */ }; @@ -63,14 +63,6 @@ private slots: void on_newAddress_clicked(); /** Copy address of currently selected address entry to clipboard */ void on_copyAddress_clicked(); - /** Open the sign message tab in the Sign/Verify Message dialog with currently selected address */ - void on_signMessage_clicked(); - /** Open the verify message tab in the Sign/Verify Message dialog with currently selected address */ - void on_verifyMessage_clicked(); - /** Open send coins dialog for currently selected address (no button) */ - void onSendCoinsAction(); - /** Generate a QR Code from the currently selected address */ - void on_showQRCode_clicked(); /** Copy label of currently selected address entry to clipboard (no button) */ void onCopyLabelAction(); /** Edit currently selected address entry (no button) */ @@ -86,8 +78,6 @@ private slots: void selectNewAddress(const QModelIndex &parent, int begin, int /*end*/); signals: - void signMessage(QString addr); - void verifyMessage(QString addr); void sendCoins(QString addr); }; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 78693971da..09f2a53680 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -331,10 +331,8 @@ int main(int argc, char *argv[]) &window, SLOT(handlePaymentRequest(SendCoinsRecipient))); QObject::connect(&walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)), paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray))); - QObject::connect(paymentServer, SIGNAL(receivedPaymentACK(QString)), - &window, SLOT(showPaymentACK(QString))); - QObject::connect(paymentServer, SIGNAL(reportError(QString, QString, unsigned int)), - guiref, SLOT(message(QString, QString, unsigned int))); + QObject::connect(paymentServer, SIGNAL(message(QString,QString,unsigned int)), + guiref, SLOT(message(QString,QString,unsigned int))); QTimer::singleShot(100, paymentServer, SLOT(uiReady())); app.exec(); diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index d9d4e3b23d..37b8743eff 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -130,9 +130,10 @@ void BitcoinAmountField::setValue(qint64 value) setText(BitcoinUnits::format(currentUnit, value)); } -void BitcoinAmountField::setReadOnly(bool fReadeOnly) +void BitcoinAmountField::setReadOnly(bool fReadOnly) { - // TODO ... + amount->setReadOnly(fReadOnly); + unit->setEnabled(!fReadOnly); } void BitcoinAmountField::unitChanged(int idx) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5afd93957b..2279d4fb4b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -7,14 +7,12 @@ #include "bitcoingui.h" -#include "transactiontablemodel.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" #include "walletmodel.h" #include "walletframe.h" #include "optionsmodel.h" -#include "transactiondescdialog.h" #include "bitcoinunits.h" #include "guiconstants.h" #include "notificator.h" @@ -157,6 +155,8 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : rpcConsole = new RPCConsole(this); connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); + // prevents an oben debug window from becoming stuck/unusable on client shutdown + connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide())); // Install event filter to be able to catch status tip events (QEvent::StatusTip) this->installEventFilter(this); @@ -192,7 +192,7 @@ void BitcoinGUI::createActions(bool fIsTestnet) tabGroup->addAction(sendCoinsAction); receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive"), this); - receiveCoinsAction->setStatusTip(tr("Show the list of addresses for receiving payments")); + receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)")); receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip()); receiveCoinsAction->setCheckable(true); receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); @@ -205,13 +205,6 @@ void BitcoinGUI::createActions(bool fIsTestnet) historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(historyAction); - addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Addresses"), this); - addressBookAction->setStatusTip(tr("Edit the list of stored addresses and labels")); - addressBookAction->setToolTip(addressBookAction->statusTip()); - addressBookAction->setCheckable(true); - addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); - tabGroup->addAction(addressBookAction); - connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); @@ -220,8 +213,6 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); - connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); - connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setStatusTip(tr("Quit application")); @@ -233,7 +224,11 @@ void BitcoinGUI::createActions(bool fIsTestnet) aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin"), this); aboutAction->setStatusTip(tr("Show information about Bitcoin")); aboutAction->setMenuRole(QAction::AboutRole); +#if QT_VERSION < 0x050000 aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this); +#else + aboutQtAction = new QAction(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this); +#endif aboutQtAction->setStatusTip(tr("Show information about Qt")); aboutQtAction->setMenuRole(QAction::AboutQtRole); optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); @@ -260,6 +255,11 @@ void BitcoinGUI::createActions(bool fIsTestnet) openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console")); + usedSendingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Used sending addresses..."), this); + usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels")); + usedReceivingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("Used &receiving addresses..."), this); + usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels")); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked())); connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); @@ -270,6 +270,8 @@ void BitcoinGUI::createActions(bool fIsTestnet) connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase())); connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab())); + connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses())); + connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses())); } void BitcoinGUI::createMenuBar() @@ -288,6 +290,9 @@ void BitcoinGUI::createMenuBar() file->addAction(signMessageAction); file->addAction(verifyMessageAction); file->addSeparator(); + file->addAction(usedSendingAddressesAction); + file->addAction(usedReceivingAddressesAction); + file->addSeparator(); file->addAction(quitAction); QMenu *settings = appMenuBar->addMenu(tr("&Settings")); @@ -311,7 +316,6 @@ void BitcoinGUI::createToolBars() toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); - toolbar->addAction(addressBookAction); } void BitcoinGUI::setClientModel(ClientModel *clientModel) @@ -441,26 +445,25 @@ void BitcoinGUI::aboutClicked() void BitcoinGUI::gotoOverviewPage() { + overviewAction->setChecked(true); if (walletFrame) walletFrame->gotoOverviewPage(); } void BitcoinGUI::gotoHistoryPage() { + historyAction->setChecked(true); if (walletFrame) walletFrame->gotoHistoryPage(); } -void BitcoinGUI::gotoAddressBookPage() -{ - if (walletFrame) walletFrame->gotoAddressBookPage(); -} - void BitcoinGUI::gotoReceiveCoinsPage() { + receiveCoinsAction->setChecked(true); if (walletFrame) walletFrame->gotoReceiveCoinsPage(); } void BitcoinGUI::gotoSendCoinsPage(QString addr) { + sendCoinsAction->setChecked(true); if (walletFrame) walletFrame->gotoSendCoinsPage(addr); } @@ -632,6 +635,8 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK))) buttons = QMessageBox::Ok; + // Ensure we get users attention + showNormalIfMinimized(); QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this); int r = mBox.exec(); if (ret != NULL) @@ -683,9 +688,8 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) QString strMessage = tr("This transaction is over the size limit. You can still send it for a fee of %1, " "which goes to the nodes that process your transaction and helps to support the network. " "Do you want to pay the fee?").arg(BitcoinUnits::formatWithUnit(clientModel->getOptionsModel()->getDisplayUnit(), nFeeRequired)); - QMessageBox::StandardButton retval = QMessageBox::question( - this, tr("Confirm transaction fee"), strMessage, - QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); + QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm transaction fee"), strMessage, + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); *payFee = (retval == QMessageBox::Yes); } @@ -728,7 +732,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event) walletFrame->gotoSendCoinsPage(); else message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."), - CClientUIInterface::ICON_WARNING); + CClientUIInterface::ICON_WARNING); } event->acceptProposedAction(); @@ -746,14 +750,17 @@ bool BitcoinGUI::eventFilter(QObject *object, QEvent *event) return QMainWindow::eventFilter(object, event); } -void BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient) -{ - walletFrame->handlePaymentRequest(recipient); -} - -void BitcoinGUI::showPaymentACK(const QString& msg) +bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient) { - message(tr("Payment acknowledged"), GUIUtil::HtmlEscape(msg), CClientUIInterface::MODAL); + // URI has to be valid + if (walletFrame->handlePaymentRequest(recipient)) + { + showNormalIfMinimized(); + gotoSendCoinsPage(); + return true; + } + else + return false; } void BitcoinGUI::setEncryptionStatus(int status) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index e2dd5dc6bc..215bb6fa05 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -5,15 +5,12 @@ #include <QSystemTrayIcon> #include <QMap> -class TransactionTableModel; class WalletFrame; class WalletView; class ClientModel; class WalletModel; class WalletStack; -class TransactionView; class OverviewPage; -class AddressBookPage; class SendCoinsDialog; class SendCoinsRecipient; class SignVerifyMessageDialog; @@ -51,24 +48,16 @@ public: The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. */ void setClientModel(ClientModel *clientModel); + /** Set the wallet model. The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending functionality. */ - bool addWallet(const QString& name, WalletModel *walletModel); bool setCurrentWallet(const QString& name); void removeAllWallets(); - /** Used by WalletView to allow access to needed QActions */ - // Todo: Use Qt signals for these - QAction * getOverviewAction() { return overviewAction; } - QAction * getHistoryAction() { return historyAction; } - QAction * getAddressBookAction() { return addressBookAction; } - QAction * getReceiveCoinsAction() { return receiveCoinsAction; } - QAction * getSendCoinsAction() { return sendCoinsAction; } - protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent *event); @@ -91,7 +80,8 @@ private: QAction *historyAction; QAction *quitAction; QAction *sendCoinsAction; - QAction *addressBookAction; + QAction *usedSendingAddressesAction; + QAction *usedReceivingAddressesAction; QAction *signMessageAction; QAction *verifyMessageAction; QAction *aboutAction; @@ -106,7 +96,6 @@ private: QSystemTrayIcon *trayIcon; Notificator *notificator; - TransactionView *transactionView; RPCConsole *rpcConsole; QMovie *syncIconMovie; @@ -143,6 +132,7 @@ public slots: @param[in] ret pointer to a bool that will be modified to whether Ok was clicked (modal only) */ void message(const QString &title, const QString &message, unsigned int style, bool *ret = NULL); + /** Asks the user whether to pay the transaction fee or to cancel the transaction. It is currently not possible to pass a return value to another thread through BlockingQueuedConnection, so an indirected pointer is used. @@ -153,8 +143,7 @@ public slots: */ void askFee(qint64 nFeeRequired, bool *payFee); - void handlePaymentRequest(const SendCoinsRecipient& recipient); - void showPaymentACK(const QString& msg); + bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); @@ -164,8 +153,6 @@ private slots: void gotoOverviewPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); - /** Switch to address book page */ - void gotoAddressBookPage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); /** Switch to send coins page */ diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index bfe9494b17..457090b1f5 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -19,8 +19,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "It is also recommended to set alertnotify so you are notified of problems;\n" "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:" -"@STRENGTH)"), +"Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!" +"3DES:@STRENGTH)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "An error occurred while setting up the RPC port %u for listening on IPv4: %s"), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -98,6 +98,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"), QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"), QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"), +QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin RPC client version"), QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"), QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"), @@ -106,6 +107,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect through socks proxy"), +QT_TRANSLATE_NOOP("bitcoin-core", "Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"), QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"), QT_TRANSLATE_NOOP("bitcoin-core", "Discover own IP address (default: 1 when listening and no -externalip)"), @@ -143,8 +145,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat fil QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Information"), QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -tor address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -minrelaytxfee=<amount>: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=<amount>: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"), @@ -172,7 +174,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"), QT_TRANSLATE_NOOP("bitcoin-core", "Select the version of socks proxy to use (4-5, default: 5)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Send command to -server or bitcoind"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send command to Bitcoin server"), QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on <ip> (default: 127.0.0.1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to debugger"), @@ -191,6 +193,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify data directory"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: bitcoind.pid)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), +QT_TRANSLATE_NOOP("bitcoin-core", "Start Bitcoin server"), QT_TRANSLATE_NOOP("bitcoin-core", "System error: "), QT_TRANSLATE_NOOP("bitcoin-core", "This help message"), QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"), @@ -202,6 +205,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind r QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"), +QT_TRANSLATE_NOOP("bitcoin-core", "Usage (deprecated, use bitcoin-cli):"), QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"), QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"), diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index b33f534f7c..212fa6974a 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -42,7 +42,7 @@ int ClientModel::getNumConnections() const int ClientModel::getNumBlocks() const { - return nBestHeight; + return chainActive.Height(); } int ClientModel::getNumBlocksAtStartup() @@ -51,19 +51,27 @@ int ClientModel::getNumBlocksAtStartup() return numBlocksAtStartup; } +quint64 ClientModel::getTotalBytesRecv() const +{ + return CNode::GetTotalBytesRecv(); +} + +quint64 ClientModel::getTotalBytesSent() const +{ + return CNode::GetTotalBytesSent(); +} + QDateTime ClientModel::getLastBlockDate() const { - if (pindexBest) - return QDateTime::fromTime_t(pindexBest->GetBlockTime()); - else if(!isTestNet()) - return QDateTime::fromTime_t(1231006505); // Genesis block's time + if (chainActive.Tip()) + return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); else - return QDateTime::fromTime_t(1296688602); // Genesis block's time (testnet) + return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network } double ClientModel::getVerificationProgress() const { - return Checkpoints::GuessVerificationProgress(pindexBest); + return Checkpoints::GuessVerificationProgress(chainActive.Tip()); } void ClientModel::updateTimer() @@ -85,6 +93,8 @@ void ClientModel::updateTimer() // ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks)); } + + emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } void ClientModel::updateNumConnections(int numConnections) diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 15074300b4..925f20acd9 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -35,6 +35,9 @@ public: int getNumBlocks() const; int getNumBlocksAtStartup(); + quint64 getTotalBytesRecv() const; + quint64 getTotalBytesSent() const; + double getVerificationProgress() const; QDateTime getLastBlockDate() const; @@ -74,6 +77,7 @@ signals: void numConnectionsChanged(int count); void numBlocksChanged(int count, int countOfPeers); void alertsChanged(const QString &warnings); + void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); //! Asynchronous message notification void message(const QString &title, const QString &message, unsigned int style); diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui index a2a7da34dd..49221f41c1 100644 --- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -10,9 +10,6 @@ <height>380</height> </rect> </property> - <property name="windowTitle"> - <string>Address Book</string> - </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QLabel" name="labelExplanation"> @@ -60,7 +57,7 @@ <string>Create a new address</string> </property> <property name="text"> - <string>&New Address</string> + <string>&New</string> </property> <property name="icon"> <iconset resource="../bitcoin.qrc"> @@ -74,7 +71,7 @@ <string>Copy the currently selected address to the system clipboard</string> </property> <property name="text"> - <string>&Copy Address</string> + <string>&Copy</string> </property> <property name="icon"> <iconset resource="../bitcoin.qrc"> @@ -83,45 +80,6 @@ </widget> </item> <item> - <widget class="QPushButton" name="showQRCode"> - <property name="text"> - <string>Show &QR Code</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/qrcode</normaloff>:/icons/qrcode</iconset> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="signMessage"> - <property name="toolTip"> - <string>Sign a message to prove you own a Bitcoin address</string> - </property> - <property name="text"> - <string>Sign &Message</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="verifyMessage"> - <property name="toolTip"> - <string>Verify a message to ensure it was signed with a specified Bitcoin address</string> - </property> - <property name="text"> - <string>&Verify Message</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset> - </property> - </widget> - </item> - <item> <widget class="QPushButton" name="deleteAddress"> <property name="toolTip"> <string>Delete the currently selected address from the list</string> @@ -163,15 +121,9 @@ </widget> </item> <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Ok</set> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>C&lose</string> </property> </widget> </item> diff --git a/src/qt/forms/editaddressdialog.ui b/src/qt/forms/editaddressdialog.ui index b4a4c1b1e9..8ff3805226 100644 --- a/src/qt/forms/editaddressdialog.ui +++ b/src/qt/forms/editaddressdialog.ui @@ -32,7 +32,7 @@ <item row="0" column="1"> <widget class="QLineEdit" name="labelEdit"> <property name="toolTip"> - <string>The label associated with this address book entry</string> + <string>The label associated with this address list entry</string> </property> </widget> </item> @@ -49,7 +49,7 @@ <item row="1" column="1"> <widget class="QLineEdit" name="addressEdit"> <property name="toolTip"> - <string>The address associated with this address book entry. This can only be modified for sending addresses.</string> + <string>The address associated with this address list entry. This can only be modified for sending addresses.</string> </property> </widget> </item> diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui deleted file mode 100644 index 1cec9066f8..0000000000 --- a/src/qt/forms/qrcodedialog.ui +++ /dev/null @@ -1,212 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>QRCodeDialog</class> - <widget class="QDialog" name="QRCodeDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>340</width> - <height>530</height> - </rect> - </property> - <property name="windowTitle"> - <string>QR Code Dialog</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QLabel" name="lblQRCode"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>300</width> - <height>300</height> - </size> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPlainTextEdit" name="outUri"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>50</height> - </size> - </property> - <property name="tabChangesFocus"> - <bool>true</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="widget" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QCheckBox" name="chkReqPayment"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Request Payment</string> - </property> - </widget> - </item> - <item> - <layout class="QFormLayout" name="formLayout"> - <property name="fieldGrowthPolicy"> - <enum>QFormLayout::AllNonFixedFieldsGrow</enum> - </property> - <item row="1" column="0"> - <widget class="QLabel" name="lblLabel"> - <property name="text"> - <string>Label:</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnLabel</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="lnLabel"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="lblMessage"> - <property name="text"> - <string>Message:</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnMessage</cstring> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="lnMessage"/> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="lblAmount"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Amount:</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnReqAmount</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="BitcoinAmountField" name="lnReqAmount"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>80</width> - <height>0</height> - </size> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="btnSaveAs"> - <property name="text"> - <string>&Save As...</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>BitcoinAmountField</class> - <extends>QLineEdit</extends> - <header>bitcoinamountfield.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>chkReqPayment</sender> - <signal>clicked(bool)</signal> - <receiver>lnReqAmount</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>92</x> - <y>285</y> - </hint> - <hint type="destinationlabel"> - <x>98</x> - <y>311</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui new file mode 100644 index 0000000000..6d1a72ecd2 --- /dev/null +++ b/src/qt/forms/receivecoinsdialog.ui @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ReceiveCoinsDialog</class> + <widget class="QWidget" name="ReceiveCoinsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>776</width> + <height>343</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="3" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>&Amount:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>reqAmount</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="BitcoinAmountField" name="reqAmount"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string>The amount to request</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>&Label:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>reqLabel</cstring> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="reqLabel"> + <property name="toolTip"> + <string>The label to associate with the receiving address</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>&Message:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>reqMessage</cstring> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="reqMessage"> + <property name="toolTip"> + <string>The message to attach to payment request</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QCheckBox" name="reuseAddress"> + <property name="toolTip"> + <string>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</string> + </property> + <property name="text"> + <string>R&euse an existing receiving address (not recommended)</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Use this form to request payments. All fields are optional.</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="clearButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Clear all fields of the form.</string> + </property> + <property name="text"> + <string>Clear</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset> + </property> + <property name="autoRepeatDelay"> + <number>300</number> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="receiveButton"> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>&Request payment</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/receiving_addresses</normaloff>:/icons/receiving_addresses</iconset> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>BitcoinAmountField</class> + <extends>QLineEdit</extends> + <header>bitcoinamountfield.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="../bitcoin.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui new file mode 100644 index 0000000000..c9cb3de69f --- /dev/null +++ b/src/qt/forms/receiverequestdialog.ui @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ReceiveRequestDialog</class> + <widget class="QDialog" name="ReceiveRequestDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>487</width> + <height>597</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QRImageWidget" name="lblQRCode"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>300</height> + </size> + </property> + <property name="toolTip"> + <string>QR Code</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="outUri"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="btnCopyURI"> + <property name="text"> + <string>Copy &URI</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnCopyAddress"> + <property name="text"> + <string>Copy &Address</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnCopyImage"> + <property name="text"> + <string>&Copy Image</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnSaveAs"> + <property name="text"> + <string>&Save Image...</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QRImageWidget</class> + <extends>QLabel</extends> + <header>receiverequestdialog.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ReceiveRequestDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>452</x> + <y>573</y> + </hint> + <hint type="destinationlabel"> + <x>243</x> + <y>298</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ReceiveRequestDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>452</x> + <y>573</y> + </hint> + <hint type="destinationlabel"> + <x>243</x> + <y>298</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index d1d8ab42a0..54c41ffb67 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -445,10 +445,271 @@ </item> </layout> </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>&Network Traffic</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="TrafficGraphWidget" name="trafficGraph" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QSlider" name="sldGraphRange"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>288</number> + </property> + <property name="pageStep"> + <number>12</number> + </property> + <property name="value"> + <number>6</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblGraphRange"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnClearTrafficGraph"> + <property name="text"> + <string>&Clear</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Totals</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="Line" name="line"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property name="palette"> + <palette> + <active> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>In:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblBytesIn"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="Line" name="line_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property name="palette"> + <palette> + <active> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Out:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblBytesOut"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>407</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </widget> </widget> </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>TrafficGraphWidget</class> + <extends>QWidget</extends> + <header>trafficgraphwidget.h</header> + <container>1</container> + <slots> + <slot>clear()</slot> + </slots> + </customwidget> + </customwidgets> <resources> <include location="../bitcoin.qrc"/> </resources> diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 2a00fc5455..67ea45d2fd 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -84,7 +84,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Remove all transaction fields</string> + <string>Clear all fields of the form.</string> </property> <property name="text"> <string>Clear &All</string> diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index 2c1cec600c..db742d633d 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -87,7 +87,7 @@ <item> <widget class="QToolButton" name="addressBookButton"> <property name="toolTip"> - <string>Choose address from address book</string> + <string>Choose previously used address</string> </property> <property name="text"> <string/> @@ -137,7 +137,7 @@ <item row="4" column="1"> <widget class="QValidatedLineEdit" name="addAsLabel"> <property name="toolTip"> - <string>Enter a label for this address to add it to your address book</string> + <string>Enter a label for this address to add it to the list of used addresses</string> </property> </widget> </item> @@ -621,7 +621,7 @@ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> <property name="buddy"> - <cstring>payAmount</cstring> + <cstring>payAmount_s</cstring> </property> </widget> </item> @@ -640,15 +640,9 @@ </item> <item row="5" column="2"> <widget class="BitcoinAmountField" name="payAmount_s"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="acceptDrops"> <bool>false</bool> </property> - <property name="readOnly"> - <bool>true</bool> - </property> </widget> </item> <item row="3" column="2"> @@ -680,7 +674,6 @@ <class>BitcoinAmountField</class> <extends>QLineEdit</extends> <header>bitcoinamountfield.h</header> - <container>1</container> </customwidget> <customwidget> <class>QValidatedLineEdit</class> diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui index 279b2a5052..04d614a1cd 100644 --- a/src/qt/forms/signverifymessagedialog.ui +++ b/src/qt/forms/signverifymessagedialog.ui @@ -58,7 +58,7 @@ <item> <widget class="QPushButton" name="addressBookButton_SM"> <property name="toolTip"> - <string>Choose an address from the address book</string> + <string>Choose previously used address</string> </property> <property name="text"> <string/> @@ -271,7 +271,7 @@ <item> <widget class="QPushButton" name="addressBookButton_VM"> <property name="toolTip"> - <string>Choose an address from the address book</string> + <string>Choose previously used address</string> </property> <property name="text"> <string/> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c951b21b80..5951cef99a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -112,6 +112,11 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) rv.label = i->second; fShouldReturnFalse = false; } + if (i->first == "message") + { + rv.message = i->second; + fShouldReturnFalse = false; + } else if (i->first == "amount") { if(!i->second.isEmpty()) @@ -148,6 +153,34 @@ bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) return parseBitcoinURI(uriInstance, out); } +QString formatBitcoinURI(const SendCoinsRecipient &info) +{ + QString ret = QString("bitcoin:%1").arg(info.address); + int paramCount = 0; + + if (info.amount) + { + ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount)); + paramCount++; + } + + if (!info.label.isEmpty()) + { + QString lbl(QUrl::toPercentEncoding(info.label)); + ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl); + paramCount++; + } + + if (!info.message.isEmpty()) + { + QString msg(QUrl::toPercentEncoding(info.message));; + ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); + paramCount++; + } + + return ret; +} + bool isDust(const QString& address, qint64 amount) { CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); @@ -190,10 +223,9 @@ void copyEntryData(QAbstractItemView *view, int column, int role) } } -QString getSaveFileName(QWidget *parent, const QString &caption, - const QString &dir, - const QString &filter, - QString *selectedSuffixOut) +QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, + const QString &filter, + QString *selectedSuffixOut) { QString selectedFilter; QString myDir; @@ -209,7 +241,8 @@ QString getSaveFileName(QWidget *parent, const QString &caption, { myDir = dir; } - QString result = QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter); + /* Directly convert path to native OS path separators */ + QString result = QDir::toNativeSeparators(QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter)); /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */ QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]"); @@ -527,7 +560,7 @@ HelpMessageBox::HelpMessageBox(QWidget *parent) : tr("Usage:") + "\n" + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; - coreOptions = QString::fromStdString(HelpMessage()); + coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); uiOptions = tr("UI options") + ":\n" + " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 8472700f48..956f550989 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -35,6 +35,7 @@ namespace GUIUtil // See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0 bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); + QString formatBitcoinURI(const SendCoinsRecipient &info); // Returns true if given address+amount meets "dust" definition bool isDust(const QString& address, qint64 amount); diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 4d1a8574d0..0dc56ac5dc 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -42,12 +42,7 @@ This product includes software developed by the OpenSSL Project for use in the O <context> <name>AddressBookPage</name> <message> - <location filename="../forms/addressbookpage.ui" line="+14"/> - <source>Address Book</source> - <translation>Address Book</translation> - </message> - <message> - <location line="+19"/> + <location filename="../forms/addressbookpage.ui" line="+30"/> <source>Double-click to edit address or label</source> <translation>Double-click to edit address or label</translation> </message> @@ -57,42 +52,32 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Create a new address</translation> </message> <message> - <location line="+14"/> + <location line="+3"/> + <source>&New</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+11"/> <source>Copy the currently selected address to the system clipboard</source> <translation>Copy the currently selected address to the system clipboard</translation> </message> <message> - <location line="-11"/> - <source>&New Address</source> - <translation>&New Address</translation> + <location line="+3"/> + <source>&Copy</source> + <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="+67"/> - <source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source> - <translation>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</translation> + <location line="+52"/> + <source>C&lose</source> + <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="+14"/> + <location filename="../addressbookpage.cpp" line="+72"/> <source>&Copy Address</source> <translation>&Copy Address</translation> </message> <message> - <location line="+11"/> - <source>Show &QR Code</source> - <translation>Show &QR Code</translation> - </message> - <message> - <location line="+11"/> - <source>Sign a message to prove you own a Bitcoin address</source> - <translation>Sign a message to prove you own a Bitcoin address</translation> - </message> - <message> - <location line="+3"/> - <source>Sign &Message</source> - <translation>Sign &Message</translation> - </message> - <message> - <location line="+25"/> + <location filename="../forms/addressbookpage.ui" line="-41"/> <source>Delete the currently selected address from the list</source> <translation>Delete the currently selected address from the list</translation> </message> @@ -107,27 +92,47 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>&Export</translation> </message> <message> - <location line="-44"/> - <source>Verify a message to ensure it was signed with a specified Bitcoin address</source> - <translation>Verify a message to ensure it was signed with a specified Bitcoin address</translation> + <location line="-27"/> + <source>&Delete</source> + <translation>&Delete</translation> </message> <message> - <location line="+3"/> - <source>&Verify Message</source> - <translation>&Verify Message</translation> + <location filename="../addressbookpage.cpp" line="-30"/> + <source>Choose the address to send coins to</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+14"/> - <source>&Delete</source> - <translation>&Delete</translation> + <location line="+1"/> + <source>Choose the address to receive coins with</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> + <source>C&hoose</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+6"/> + <source>Sending addresses</source> + <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="-5"/> + <location line="+1"/> + <source>Receiving addresses</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source> <translation>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</translation> </message> <message> - <location line="+13"/> + <location line="+4"/> + <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> <source>Copy &Label</source> <translation>Copy &Label</translation> </message> @@ -137,14 +142,9 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>&Edit</translation> </message> <message> - <location line="+1"/> - <source>Send &Coins</source> - <translation>Send &Coins</translation> - </message> - <message> - <location line="+265"/> - <source>Export Address Book Data</source> - <translation>Export Address Book Data</translation> + <location line="+197"/> + <source>Export Address List</source> + <translation type="unfinished"></translation> </message> <message> <location line="+1"/> @@ -324,17 +324,17 @@ This product includes software developed by the OpenSSL Project for use in the O <context> <name>BitcoinGUI</name> <message> - <location filename="../bitcoingui.cpp" line="+255"/> + <location filename="../bitcoingui.cpp" line="+250"/> <source>Sign &message...</source> <translation>Sign &message...</translation> </message> <message> - <location line="+246"/> + <location line="+254"/> <source>Synchronizing with network...</source> <translation>Synchronizing with network...</translation> </message> <message> - <location line="-321"/> + <location line="-324"/> <source>&Overview</source> <translation>&Overview</translation> </message> @@ -354,17 +354,7 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Browse transaction history</translation> </message> <message> - <location line="+7"/> - <source>Edit the list of stored addresses and labels</source> - <translation>Edit the list of stored addresses and labels</translation> - </message> - <message> - <location line="-14"/> - <source>Show the list of addresses for receiving payments</source> - <translation>Show the list of addresses for receiving payments</translation> - </message> - <message> - <location line="+31"/> + <location line="+15"/> <source>E&xit</source> <translation>E&xit</translation> </message> @@ -379,12 +369,13 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Show information about Bitcoin</translation> </message> <message> + <location line="+3"/> <location line="+2"/> <source>About &Qt</source> <translation>About &Qt</translation> </message> <message> - <location line="+1"/> + <location line="+2"/> <source>Show information about Qt</source> <translation>Show information about Qt</translation> </message> @@ -409,7 +400,7 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>&Change Passphrase...</translation> </message> <message> - <location line="+251"/> + <location line="+259"/> <source>Importing blocks from disk...</source> <translation>Importing blocks from disk...</translation> </message> @@ -419,12 +410,12 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Reindexing blocks on disk...</translation> </message> <message> - <location line="-319"/> + <location line="-322"/> <source>Send coins to a Bitcoin address</source> <translation>Send coins to a Bitcoin address</translation> </message> <message> - <location line="+52"/> + <location line="+47"/> <source>Modify configuration options for Bitcoin</source> <translation>Modify configuration options for Bitcoin</translation> </message> @@ -454,20 +445,20 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>&Verify message...</translation> </message> <message> - <location line="-183"/> + <location line="-180"/> <location line="+6"/> - <location line="+508"/> + <location line="+513"/> <source>Bitcoin</source> <translation>Bitcoin</translation> </message> <message> - <location line="-514"/> + <location line="-519"/> <location line="+6"/> <source>Wallet</source> <translation>Wallet</translation> </message> <message> - <location line="+107"/> + <location line="+109"/> <source>&Send</source> <translation>&Send</translation> </message> @@ -477,18 +468,13 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>&Receive</translation> </message> <message> - <location line="+14"/> - <source>&Addresses</source> - <translation>&Addresses</translation> - </message> - <message> - <location line="+23"/> + <location line="+28"/> <location line="+2"/> <source>&About Bitcoin</source> <translation>&About Bitcoin</translation> </message> <message> - <location line="+10"/> + <location line="+14"/> <location line="+2"/> <source>&Show / Hide</source> <translation>&Show / Hide</translation> @@ -514,12 +500,12 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Verify messages to ensure they were signed with specified Bitcoin addresses</translation> </message> <message> - <location line="+28"/> + <location line="+35"/> <source>&File</source> <translation>&File</translation> </message> <message> - <location line="+7"/> + <location line="+10"/> <source>&Settings</source> <translation>&Settings</translation> </message> @@ -534,19 +520,44 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Tabs toolbar</translation> </message> <message> - <location line="-228"/> - <location line="+288"/> + <location line="-235"/> + <location line="+294"/> <source>[testnet]</source> <translation>[testnet]</translation> </message> <message> - <location line="-5"/> + <location line="-177"/> + <source>Request payments (generates QR codes and bitcoin: URIs)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+63"/> + <source>&Used sending addresses...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Show the list of used sending addresses and labels</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Used &receiving addresses...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Show the list of used receiving addresses and labels</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+106"/> <location line="+5"/> <source>Bitcoin client</source> <translation>Bitcoin client</translation> </message> <message numerus="yes"> - <location line="+121"/> + <location line="+120"/> <source>%n active connection(s) to Bitcoin network</source> <translation> <numerusform>%n active connection to Bitcoin network</numerusform> @@ -608,7 +619,7 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Transactions after this will not yet be visible.</translation> </message> <message> - <location line="+22"/> + <location line="+27"/> <source>Error</source> <translation>Error</translation> </message> @@ -623,12 +634,12 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Information</translation> </message> <message> - <location line="+73"/> + <location line="+77"/> <source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source> <translation>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</translation> </message> <message> - <location line="-143"/> + <location line="-152"/> <source>Up to date</source> <translation>Up to date</translation> </message> @@ -638,7 +649,7 @@ This product includes software developed by the OpenSSL Project for use in the O <translation>Catching up...</translation> </message> <message> - <location line="+116"/> + <location line="+124"/> <source>Confirm transaction fee</source> <translation>Confirm transaction fee</translation> </message> @@ -676,13 +687,7 @@ Address: %4 <translation>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation> </message> <message> - <location line="+27"/> - <location line="+2"/> - <source>Payment acknowledged</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+17"/> + <location line="+45"/> <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> <translation>Wallet is <b>encrypted</b> and currently <b>unlocked</b></translation> </message> @@ -700,7 +705,7 @@ Address: %4 <context> <name>ClientModel</name> <message> - <location filename="../clientmodel.cpp" line="+106"/> + <location filename="../clientmodel.cpp" line="+115"/> <source>Network Alert</source> <translation>Network Alert</translation> </message> @@ -719,18 +724,18 @@ Address: %4 </message> <message> <location line="+10"/> - <source>The label associated with this address book entry</source> - <translation>The label associated with this address book entry</translation> + <source>The label associated with this address list entry</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> - <source>&Address</source> - <translation>&Address</translation> + <location line="+17"/> + <source>The address associated with this address list entry. This can only be modified for sending addresses.</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+10"/> - <source>The address associated with this address book entry. This can only be modified for sending addresses.</source> - <translation>The address associated with this address book entry. This can only be modified for sending addresses.</translation> + <location line="-10"/> + <source>&Address</source> + <translation>&Address</translation> </message> <message> <location filename="../editaddressdialog.cpp" line="+21"/> @@ -804,7 +809,7 @@ Address: %4 <context> <name>GUIUtil::HelpMessageBox</name> <message> - <location filename="../guiutil.cpp" line="+525"/> + <location filename="../guiutil.cpp" line="+558"/> <location line="+13"/> <source>Bitcoin-Qt</source> <translation>Bitcoin-Qt</translation> @@ -1181,8 +1186,23 @@ Address: %4 <context> <name>PaymentServer</name> <message> - <location filename="../paymentserver.cpp" line="+450"/> - <location line="+41"/> + <location filename="../paymentserver.cpp" line="+392"/> + <source>URI handling</source> + <translation type="unfinished">URI handling</translation> + </message> + <message> + <location line="+1"/> + <source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> + <translation type="unfinished">URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation> + </message> + <message> + <location line="+69"/> + <source>Requested payment amount of %1 is too small (considered dust).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+4"/> + <location line="+37"/> <source>Payment request error</source> <translation type="unfinished"></translation> </message> @@ -1193,12 +1213,27 @@ Address: %4 </message> <message> <location line="+38"/> - <source>Refund from</source> + <source>Refund from %1</source> <translation type="unfinished"></translation> </message> <message> - <location line="+46"/> - <location line="+28"/> + <location line="+42"/> + <source>Error communicating with %1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+31"/> + <source>Bad response from server %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+32"/> + <source>Payment acknowledged</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-58"/> + <location line="+30"/> <location line="+17"/> <source>Network request error</source> <translation type="unfinished"></translation> @@ -1207,7 +1242,7 @@ Address: %4 <context> <name>QObject</name> <message> - <location filename="../bitcoin.cpp" line="+111"/> + <location filename="../bitcoin.cpp" line="+114"/> <location line="+5"/> <location filename="../intro.cpp" line="-32"/> <source>Bitcoin</source> @@ -1228,78 +1263,28 @@ Address: %4 <source>Error: Specified data directory "%1" can not be created.</source> <translation>Error: Specified data directory "%1" can not be created.</translation> </message> - <message> - <location filename="../paymentserver.cpp" line="-175"/> - <source>Requested payment amount (%1) too small</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+126"/> - <source>Error communicating with %1: %2</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+29"/> - <source>Bad response from server %1</source> - <translation type="unfinished"></translation> - </message> </context> <context> - <name>QRCodeDialog</name> - <message> - <location filename="../forms/qrcodedialog.ui" line="+14"/> - <source>QR Code Dialog</source> - <translation>QR Code Dialog</translation> - </message> - <message> - <location line="+59"/> - <source>Request Payment</source> - <translation>Request Payment</translation> - </message> - <message> - <location line="+56"/> - <source>Amount:</source> - <translation>Amount:</translation> - </message> - <message> - <location line="-44"/> - <source>Label:</source> - <translation>Label:</translation> - </message> + <name>QRImageWidget</name> <message> - <location line="+19"/> - <source>Message:</source> - <translation>Message:</translation> - </message> - <message> - <location line="+71"/> - <source>&Save As...</source> - <translation>&Save As...</translation> - </message> - <message> - <location filename="../qrcodedialog.cpp" line="+64"/> - <source>Error encoding URI into QR Code.</source> - <translation>Error encoding URI into QR Code.</translation> - </message> - <message> - <location line="+40"/> - <source>The entered amount is invalid, please check.</source> - <translation>The entered amount is invalid, please check.</translation> + <location filename="../receiverequestdialog.cpp" line="+32"/> + <source>&Save Image...</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+23"/> - <source>Resulting URI too long, try to reduce the text for label / message.</source> - <translation>Resulting URI too long, try to reduce the text for label / message.</translation> + <location line="+3"/> + <source>&Copy Image</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+25"/> + <location line="+28"/> <source>Save QR Code</source> - <translation>Save QR Code</translation> + <translation type="unfinished">Save QR Code</translation> </message> <message> <location line="+0"/> <source>PNG Images (*.png)</source> - <translation>PNG Images (*.png)</translation> + <translation type="unfinished">PNG Images (*.png)</translation> </message> </context> <context> @@ -1319,7 +1304,7 @@ Address: %4 <location line="+53"/> <location line="+23"/> <location line="+23"/> - <location filename="../rpcconsole.cpp" line="+345"/> + <location filename="../rpcconsole.cpp" line="+352"/> <source>N/A</source> <translation>N/A</translation> </message> @@ -1404,7 +1389,32 @@ Address: %4 <translation>&Console</translation> </message> <message> - <location line="-260"/> + <location line="+72"/> + <source>&Network Traffic</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+52"/> + <source>&Clear</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+13"/> + <source>Totals</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+64"/> + <source>In:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+80"/> + <source>Out:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-541"/> <source>Build date</source> <translation>Build date</translation> </message> @@ -1448,20 +1458,184 @@ Address: %4 <source>Type <b>help</b> for an overview of available commands.</source> <translation>Type <b>help</b> for an overview of available commands.</translation> </message> + <message> + <location line="+128"/> + <source>%1 B</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 KB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 MB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 GB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>%1 m</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> + <source>%1 h</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>%1 h %2 m</source> + <translation type="unfinished"></translation> + </message> </context> <context> - <name>SendCoinsDialog</name> + <name>ReceiveCoinsDialog</name> + <message> + <location filename="../forms/receivecoinsdialog.ui" line="+22"/> + <source>&Amount:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+16"/> + <source>The amount to request</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>&Label:</source> + <translation type="unfinished">&Label:</translation> + </message> + <message> + <location line="+10"/> + <source>The label to associate with the receiving address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>&Message:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+10"/> + <source>The message to attach to payment request</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+14"/> + <source>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>R&euse an existing receiving address (not recommended)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>Use this form to request payments. All fields are optional.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+17"/> + <source>Clear all fields of the form.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Clear</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+36"/> + <source>&Request payment</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>ReceiveRequestDialog</name> + <message> + <location filename="../forms/receiverequestdialog.ui" line="+29"/> + <source>QR Code</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+46"/> + <source>Copy &URI</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>Copy &Address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>&Copy Image</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>&Save Image...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../receiverequestdialog.cpp" line="+58"/> + <source>Request payment to %1</source> + <translation type="unfinished"></translation> + </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="+14"/> - <location filename="../sendcoinsdialog.cpp" line="+138"/> - <location line="+5"/> - <location line="+5"/> - <location line="+5"/> <location line="+6"/> + <source>Payment information</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>URI</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>Address</source> + <translation type="unfinished">Address</translation> + </message> + <message> + <location line="+2"/> + <source>Amount</source> + <translation type="unfinished">Amount</translation> + </message> + <message> + <location line="+2"/> + <source>Label</source> + <translation type="unfinished">Label</translation> + </message> + <message> + <location line="+2"/> + <source>Message</source> + <translation type="unfinished">Message</translation> + </message> + <message> + <location line="+10"/> + <source>Resulting URI too long, try to reduce the text for label / message.</source> + <translation type="unfinished">Resulting URI too long, try to reduce the text for label / message.</translation> + </message> + <message> <location line="+5"/> - <location line="+50"/> - <location line="+145"/> - <location line="+9"/> + <source>Error encoding URI into QR Code.</source> + <translation type="unfinished">Error encoding URI into QR Code.</translation> + </message> +</context> +<context> + <name>SendCoinsDialog</name> + <message> + <location filename="../forms/sendcoinsdialog.ui" line="+14"/> + <location filename="../sendcoinsdialog.cpp" line="+140"/> + <location line="+213"/> <source>Send Coins</source> <translation>Send Coins</translation> </message> @@ -1477,8 +1651,8 @@ Address: %4 </message> <message> <location line="+20"/> - <source>Remove all transaction fields</source> - <translation>Remove all transaction fields</translation> + <source>Clear all fields of the form.</source> + <translation type="unfinished"></translation> </message> <message> <location line="+3"/> @@ -1506,47 +1680,44 @@ Address: %4 <translation>S&end</translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="-170"/> + <location filename="../sendcoinsdialog.cpp" line="-154"/> <source>Confirm send coins</source> <translation>Confirm send coins</translation> </message> <message> - <location line="-97"/> - <source>to</source> - <translation type="unfinished">to</translation> - </message> - <message> - <location line="+15"/> - <source><b>%1</b> to %2</source> + <location line="-90"/> + <location line="+5"/> + <location line="+5"/> + <source>%1 to %2</source> <translation type="unfinished"></translation> </message> <message> - <location line="+23"/> + <location line="+26"/> <source>The recipient address is not valid, please recheck.</source> <translation>The recipient address is not valid, please recheck.</translation> </message> <message> - <location line="+5"/> + <location line="+4"/> <source>The amount to pay must be larger than 0.</source> <translation>The amount to pay must be larger than 0.</translation> </message> <message> - <location line="+5"/> + <location line="+4"/> <source>The amount exceeds your balance.</source> <translation>The amount exceeds your balance.</translation> </message> <message> - <location line="+5"/> + <location line="+4"/> <source>The total exceeds your balance when the %1 transaction fee is included.</source> <translation>The total exceeds your balance when the %1 transaction fee is included.</translation> </message> <message> - <location line="+6"/> + <location line="+5"/> <source>Duplicate address found, can only send to each address once per send operation.</source> <translation>Duplicate address found, can only send to each address once per send operation.</translation> </message> <message> - <location line="+5"/> + <location line="+4"/> <source>Error: Transaction creation failed!</source> <translation>Error: Transaction creation failed!</translation> </message> @@ -1571,12 +1742,12 @@ Address: %4 <translation>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</translation> </message> <message> - <location line="+145"/> + <location line="+144"/> <source>Payment request expired</source> <translation type="unfinished"></translation> </message> <message> - <location line="+9"/> + <location line="+8"/> <source>Invalid payment address %1</source> <translation type="unfinished"></translation> </message> @@ -1584,49 +1755,38 @@ Address: %4 <context> <name>SendCoinsEntry</name> <message> - <location filename="../forms/sendcoinsentry.ui" line="+24"/> - <source>Form</source> - <translation>Form</translation> - </message> - <message> - <location line="+15"/> - <location line="+588"/> + <location filename="../forms/sendcoinsentry.ui" line="+33"/> + <location line="+585"/> <source>A&mount:</source> <translation>A&mount:</translation> </message> <message> - <location line="-575"/> - <location line="+588"/> + <location line="-572"/> + <location line="+585"/> <source>Pay &To:</source> <translation>Pay &To:</translation> </message> <message> - <location line="-554"/> + <location line="-551"/> <source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> <translation>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation> </message> <message> - <location line="+60"/> <location filename="../sendcoinsentry.cpp" line="+28"/> <source>Enter a label for this address to add it to your address book</source> <translation>Enter a label for this address to add it to your address book</translation> </message> <message> - <location line="-78"/> + <location filename="../forms/sendcoinsentry.ui" line="-18"/> <source>&Label:</source> <translation>&Label:</translation> </message> <message> - <location line="-54"/> - <source>StackedWidget</source> + <location line="+28"/> + <source>Choose previously used address</source> <translation type="unfinished"></translation> </message> <message> - <location line="+82"/> - <source>Choose address from address book</source> - <translation>Choose address from address book</translation> - </message> - <message> <location line="+10"/> <source>Alt+A</source> <translation>Alt+A</translation> @@ -1647,21 +1807,16 @@ Address: %4 <translation>Remove this recipient</translation> </message> <message> - <location line="+466"/> - <source>SecureSend</source> + <location line="+16"/> + <source>Enter a label for this address to add it to the list of used addresses</source> <translation type="unfinished"></translation> </message> <message> - <location line="+18"/> + <location line="+465"/> <source>Memo:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+63"/> - <source>message from merchant</source> - <translation type="unfinished"></translation> - </message> - <message> <location filename="../sendcoinsentry.cpp" line="+1"/> <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> <translation>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation> @@ -1692,8 +1847,8 @@ Address: %4 <message> <location line="+10"/> <location line="+213"/> - <source>Choose an address from the address book</source> - <translation>Choose an address from the address book</translation> + <source>Choose previously used address</source> + <translation type="unfinished"></translation> </message> <message> <location line="-203"/> @@ -1874,6 +2029,14 @@ Address: %4 </message> </context> <context> + <name>TrafficGraphWidget</name> + <message> + <location filename="../trafficgraphwidget.cpp" line="+75"/> + <source>KB/s</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>TransactionDesc</name> <message> <location filename="../transactiondesc.cpp" line="+22"/> @@ -1952,12 +2115,12 @@ Address: %4 <location line="+12"/> <location line="+45"/> <location line="+17"/> - <location line="+45"/> + <location line="+48"/> <source>Credit</source> <translation>Credit</translation> </message> <message numerus="yes"> - <location line="-117"/> + <location line="-120"/> <source>matures in %n more block(s)</source> <translation> <numerusform>matures in %n more block</numerusform> @@ -1973,12 +2136,12 @@ Address: %4 <location line="+44"/> <location line="+8"/> <location line="+15"/> - <location line="+45"/> + <location line="+48"/> <source>Debit</source> <translation>Debit</translation> </message> <message> - <location line="-54"/> + <location line="-57"/> <source>Transaction fee</source> <translation>Transaction fee</translation> </message> @@ -2008,12 +2171,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+5"/> - <source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> - <translation>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</translation> + <location line="+7"/> + <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> + <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> + <location line="+8"/> <source>Debug information</source> <translation>Debug information</translation> </message> @@ -2043,7 +2206,7 @@ Address: %4 <translation>false</translation> </message> <message> - <location line="-224"/> + <location line="-227"/> <source>, has not been successfully broadcast yet</source> <translation>, has not been successfully broadcast yet</translation> </message> @@ -2388,7 +2551,7 @@ Address: %4 <translation>Export the data in the current tab to a file</translation> </message> <message> - <location line="+198"/> + <location line="+183"/> <source>Backup Wallet</source> <translation>Backup Wallet</translation> </message> @@ -2421,22 +2584,17 @@ Address: %4 <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="+101"/> + <location filename="../bitcoinstrings.cpp" line="+102"/> <source>Bitcoin version</source> <translation>Bitcoin version</translation> </message> <message> - <location line="+104"/> + <location line="+107"/> <source>Usage:</source> <translation>Usage:</translation> </message> <message> - <location line="-30"/> - <source>Send command to -server or bitcoind</source> - <translation>Send command to -server or bitcoind</translation> - </message> - <message> - <location line="-23"/> + <location line="-55"/> <source>List commands</source> <translation>List commands</translation> </message> @@ -2491,12 +2649,12 @@ Address: %4 <translation>Specify your own public address</translation> </message> <message> - <location line="+3"/> + <location line="+4"/> <source>Threshold for disconnecting misbehaving peers (default: 100)</source> <translation>Threshold for disconnecting misbehaving peers (default: 100)</translation> </message> <message> - <location line="-139"/> + <location line="-142"/> <source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source> <translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation> </message> @@ -2516,17 +2674,17 @@ Address: %4 <translation>Accept command line and JSON-RPC commands</translation> </message> <message> - <location line="+77"/> + <location line="+79"/> <source>Run in the background as a daemon and accept commands</source> <translation>Run in the background as a daemon and accept commands</translation> </message> <message> - <location line="+38"/> + <location line="+40"/> <source>Use the test network</source> <translation>Use the test network</translation> </message> <message> - <location line="-114"/> + <location line="-118"/> <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source> <translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation> </message> @@ -2556,7 +2714,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. </translation> </message> <message> - <location line="+17"/> + <location line="+12"/> + <source>Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> <source>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</source> <translation>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</translation> </message> @@ -2636,6 +2799,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Attempt to recover private keys from a corrupt wallet.dat</translation> </message> <message> + <location line="+1"/> + <source>Bitcoin RPC client version</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+2"/> <source>Block creation options:</source> <translation>Block creation options:</translation> @@ -2646,7 +2814,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Connect only to the specified node(s)</translation> </message> <message> - <location line="+3"/> + <location line="+2"/> + <source>Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> <source>Corrupted block database detected</source> <translation>Corrupted block database detected</translation> </message> @@ -2776,7 +2949,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation> </message> <message> - <location line="+18"/> + <location line="+3"/> + <source>Invalid -onion address: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+15"/> <source>Not enough file descriptors available.</source> <translation>Not enough file descriptors available.</translation> </message> @@ -2786,7 +2964,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Rebuild block chain index from current blk000??.dat files</translation> </message> <message> - <location line="+16"/> + <location line="+6"/> + <source>Send command to Bitcoin server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+10"/> <source>Set the number of threads to service RPC calls (default: 4)</source> <translation>Set the number of threads to service RPC calls (default: 4)</translation> </message> @@ -2796,7 +2979,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Specify wallet file (within data directory)</translation> </message> <message> - <location line="+20"/> + <location line="+2"/> + <source>Start Bitcoin server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+12"/> + <source>Usage (deprecated, use bitcoin-cli):</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+8"/> <source>Verifying blocks...</source> <translation>Verifying blocks...</translation> </message> @@ -2816,12 +3009,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>You need to rebuild the database using -reindex to change -txindex</translation> </message> <message> - <location line="-76"/> + <location line="-78"/> <source>Imports blocks from external blk000??.dat file</source> <translation>Imports blocks from external blk000??.dat file</translation> </message> <message> - <location line="-96"/> + <location line="-98"/> <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source> <translation>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</translation> </message> @@ -2831,17 +3024,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)</translation> </message> <message> - <location line="+81"/> + <location line="+83"/> <source>Information</source> <translation>Information</translation> </message> <message> - <location line="+3"/> - <source>Invalid -tor address: '%s'</source> - <translation>Invalid -tor address: '%s'</translation> - </message> - <message> - <location line="+1"/> + <location line="+4"/> <source>Invalid amount for -minrelaytxfee=<amount>: '%s'</source> <translation>Invalid amount for -minrelaytxfee=<amount>: '%s'</translation> </message> @@ -2936,7 +3124,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Specify connection timeout in milliseconds (default: 5000)</translation> </message> <message> - <location line="+5"/> + <location line="+6"/> <source>System error: </source> <translation>System error: </translation> </message> @@ -2956,7 +3144,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Transaction too large</translation> </message> <message> - <location line="+7"/> + <location line="+8"/> <source>Use UPnP to map the listening port (default: 0)</source> <translation>Use UPnP to map the listening port (default: 0)</translation> </message> @@ -2991,32 +3179,32 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>wallet.dat corrupt, salvage failed</translation> </message> <message> - <location line="-52"/> + <location line="-54"/> <source>Password for JSON-RPC connections</source> <translation>Password for JSON-RPC connections</translation> </message> <message> - <location line="-68"/> + <location line="-70"/> <source>Allow JSON-RPC connections from specified IP address</source> <translation>Allow JSON-RPC connections from specified IP address</translation> </message> <message> - <location line="+77"/> + <location line="+79"/> <source>Send commands to node running on <ip> (default: 127.0.0.1)</source> <translation>Send commands to node running on <ip> (default: 127.0.0.1)</translation> </message> <message> - <location line="-124"/> + <location line="-126"/> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation> </message> <message> - <location line="+152"/> + <location line="+155"/> <source>Upgrade wallet to latest format</source> <translation>Upgrade wallet to latest format</translation> </message> <message> - <location line="-22"/> + <location line="-23"/> <source>Set key pool size to <n> (default: 100)</source> <translation>Set key pool size to <n> (default: 100)</translation> </message> @@ -3026,12 +3214,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Rescan the block chain for missing wallet transactions</translation> </message> <message> - <location line="+36"/> + <location line="+38"/> <source>Use OpenSSL (https) for JSON-RPC connections</source> <translation>Use OpenSSL (https) for JSON-RPC connections</translation> </message> <message> - <location line="-27"/> + <location line="-29"/> <source>Server certificate file (default: server.cert)</source> <translation>Server certificate file (default: server.cert)</translation> </message> @@ -3041,12 +3229,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Server private key (default: server.pem)</translation> </message> <message> - <location line="-159"/> - <source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source> - <translation>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</translation> - </message> - <message> - <location line="+174"/> + <location line="+16"/> <source>This help message</source> <translation>This help message</translation> </message> @@ -3056,17 +3239,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Unable to bind to %s on this computer (bind returned error %d, %s)</translation> </message> <message> - <location line="-93"/> + <location line="-95"/> <source>Connect through socks proxy</source> <translation>Connect through socks proxy</translation> </message> <message> - <location line="-10"/> + <location line="-11"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation> </message> <message> - <location line="+56"/> + <location line="+58"/> <source>Loading addresses...</source> <translation>Loading addresses...</translation> </message> @@ -3081,17 +3264,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Error loading wallet.dat: Wallet requires newer version of Bitcoin</translation> </message> <message> - <location line="+96"/> + <location line="+98"/> <source>Wallet needed to be rewritten: restart Bitcoin to complete</source> <translation>Wallet needed to be rewritten: restart Bitcoin to complete</translation> </message> <message> - <location line="-98"/> + <location line="-100"/> <source>Error loading wallet.dat</source> <translation>Error loading wallet.dat</translation> </message> <message> - <location line="+29"/> + <location line="+30"/> <source>Invalid -proxy address: '%s'</source> <translation>Invalid -proxy address: '%s'</translation> </message> @@ -3106,7 +3289,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Unknown -socks proxy version requested: %i</translation> </message> <message> - <location line="-98"/> + <location line="-100"/> <source>Cannot resolve -bind address: '%s'</source> <translation>Cannot resolve -bind address: '%s'</translation> </message> @@ -3116,7 +3299,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Cannot resolve -externalip address: '%s'</translation> </message> <message> - <location line="+45"/> + <location line="+46"/> <source>Invalid amount for -paytxfee=<amount>: '%s'</source> <translation>Invalid amount for -paytxfee=<amount>: '%s'</translation> </message> @@ -3136,7 +3319,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Loading block index...</translation> </message> <message> - <location line="-58"/> + <location line="-60"/> <source>Add a node to connect to and attempt to keep the connection open</source> <translation>Add a node to connect to and attempt to keep the connection open</translation> </message> @@ -3146,7 +3329,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Unable to bind to %s on this computer. Bitcoin is probably already running.</translation> </message> <message> - <location line="+67"/> + <location line="+69"/> <source>Fee per KB to add to transactions you send</source> <translation>Fee per KB to add to transactions you send</translation> </message> @@ -3156,7 +3339,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Loading wallet...</translation> </message> <message> - <location line="-53"/> + <location line="-54"/> <source>Cannot downgrade wallet</source> <translation>Cannot downgrade wallet</translation> </message> @@ -3166,7 +3349,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Cannot write default address</translation> </message> <message> - <location line="+65"/> + <location line="+66"/> <source>Rescanning...</source> <translation>Rescanning...</translation> </message> @@ -3176,17 +3359,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Done loading</translation> </message> <message> - <location line="+84"/> + <location line="+85"/> <source>To use the %s option</source> <translation>To use the %s option</translation> </message> <message> - <location line="-76"/> + <location line="-77"/> <source>Error</source> <translation>Error</translation> </message> <message> - <location line="-31"/> + <location line="-33"/> <source>You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions.</source> diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 95efc58320..4db048dcce 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -6,6 +6,9 @@ #include "bitcoinunits.h" #include "init.h" +#include "core.h" +#include "wallet.h" +#include "netbase.h" #include "walletdb.h" #include "guiutil.h" diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index f6a898ff7c..c8afd837d2 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -75,8 +75,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c digestAlgorithm = EVP_sha1(); } else if (paymentRequest.pki_type() == "none") { - if (fDebug) - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; + qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; return false; } else { diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 72f75b42e6..0f386680ac 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2012 The Bitcoin developers +// Copyright (c) 2009-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. @@ -48,6 +48,7 @@ const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds const QString BITCOIN_IPC_PREFIX("bitcoin:"); const char* BITCOIN_REQUEST_MIMETYPE = "application/bitcoin-paymentrequest"; const char* BITCOIN_PAYMENTACK_MIMETYPE = "application/bitcoin-paymentack"; +const char* BITCOIN_PAYMENTACK_CONTENTTYPE = "application/bitcoin-payment"; X509_STORE* PaymentServer::certStore = NULL; void PaymentServer::freeCertStore() @@ -86,9 +87,7 @@ static QList<QString> savedPaymentRequests; static void ReportInvalidCertificate(const QSslCertificate& cert) { - if (fDebug) { - qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName); - } + qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName); } // @@ -159,8 +158,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) continue; } } - if (fDebug) - qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates"; + qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates"; // Project for another day: // Fetch certificate revocation lists, and add them to certStore. @@ -188,7 +186,7 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[]) if (arg.startsWith("-")) continue; - if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: + if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI { savedPaymentRequests.append(arg); @@ -219,9 +217,9 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[]) } else { - qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << argv[i]; // Printing to debug.log is about the best we can do here, the // GUI hasn't started yet so we can't pop up a message box. + qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; } } @@ -245,16 +243,24 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[]) delete socket; fResult = true; } + return fResult; } -PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : QObject(parent), saveURIs(true) +PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : + QObject(parent), + saveURIs(true), + uriServer(0), + netManager(0), + optionsModel(0) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; - // Install global event filter to catch QFileOpenEvents on the mac (sent when you click bitcoin: links) + // Install global event filter to catch QFileOpenEvents + // on Mac: sent when you click bitcoin: links + // other OSes: helpful when dealing with payment request files (in the future) if (parent) parent->installEventFilter(this); @@ -269,8 +275,10 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : QObject(p if (!uriServer->listen(name)) qDebug() << "PaymentServer::PaymentServer : Cannot start bitcoin: click-to-pay handler"; - else + else { connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection())); + connect(this, SIGNAL(receivedPaymentACK(QString)), this, SLOT(handlePaymentACK(QString))); + } } // netManager is null until uiReady() is called @@ -309,10 +317,10 @@ void PaymentServer::initNetManager() if (netManager != NULL) delete netManager; - // netManager is used to fetch paymentrequests given in bitcoin: URI's + // netManager is used to fetch paymentrequests given in bitcoin: URIs netManager = new QNetworkAccessManager(this); - // Use proxy settings from optionsModel: + // Use proxy settings from optionsModel QString proxyIP; quint16 proxyPort; if (optionsModel->getProxySettings(proxyIP, proxyPort)) @@ -359,23 +367,27 @@ void PaymentServer::handleURIOrFile(const QString& s) #endif if (uri.hasQueryItem("request")) { - QByteArray temp; temp.append(uri.queryItemValue("request")); + QByteArray temp; + temp.append(uri.queryItemValue("request")); QString decoded = QUrl::fromPercentEncoding(temp); QUrl fetchUrl(decoded, QUrl::StrictMode); - if (fDebug) - qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")"; + qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")"; if (fetchUrl.isValid()) fetchRequest(fetchUrl); else - qDebug() << "PaymentServer::handleURIOrFile : Invalid url: " << fetchUrl; + qDebug() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl; return; } SendCoinsRecipient recipient; if (GUIUtil::parseBitcoinURI(s, &recipient)) emit receivedPaymentRequest(recipient); + else + emit message(tr("URI handling"), + tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."), + CClientUIInterface::ICON_WARNING); return; } @@ -407,10 +419,10 @@ void PaymentServer::handleURIConnection() if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) { return; } - QString message; - in >> message; + QString msg; + in >> msg; - handleURIOrFile(message); + handleURIOrFile(msg); } bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPlus& request) @@ -443,11 +455,11 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) { CTxOut txOut(sendingTo.second, sendingTo.first); if (txOut.IsDust(CTransaction::nMinRelayTxFee)) { - QString message = QObject::tr("Requested payment amount (%1) too small") + QString msg = tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)); - qDebug() << "PaymentServer::processPaymentRequest : " << message; - emit reportError(tr("Payment request error"), message, CClientUIInterface::MODAL); + qDebug() << "PaymentServer::processPaymentRequest : " << msg; + emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); return false; } @@ -459,8 +471,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen if (request.getMerchant(PaymentServer::certStore, recipients[0].authenticatedMerchant)) { recipients[0].paymentRequest = request; recipients[0].amount = totalAmount; - if (fDebug) - qDebug() << "PaymentServer::processPaymentRequest : Payment request from " << recipients[0].authenticatedMerchant; + qDebug() << "PaymentServer::processPaymentRequest : Payment request from " << recipients[0].authenticatedMerchant; } else { recipients.clear(); @@ -471,26 +482,21 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen recipients.append(SendCoinsRecipient()); recipients[i].amount = sendingTo.second; QString memo = QString::fromStdString(request.getDetails().memo()); -#if QT_VERSION < 0x050000 - recipients[i].label = Qt::escape(memo); -#else - recipients[i].label = memo.toHtmlEscaped(); -#endif + recipients[i].label = GUIUtil::HtmlEscape(memo); CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { if (i == 0) // Tie request to first pay-to, we don't want multiple ACKs recipients[i].paymentRequest = request; recipients[i].address = QString::fromStdString(CBitcoinAddress(dest).ToString()); - if (fDebug) - qDebug() << "PaymentServer::processPaymentRequest : Payment request, insecure " << recipients[i].address; + qDebug() << "PaymentServer::processPaymentRequest : Payment request, insecure " << recipients[i].address; } else { // Insecure payments to custom bitcoin addresses are not supported // (there is no good way to tell the user where they are paying in a way // they'd have a chance of understanding). - emit reportError(tr("Payment request error"), - tr("Insecure requests to custom payment scripts unsupported"), - CClientUIInterface::MODAL); + emit message(tr("Payment request error"), + tr("Insecure requests to custom payment scripts unsupported"), + CClientUIInterface::MSG_ERROR); return false; } } @@ -518,7 +524,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien QNetworkRequest netRequest; netRequest.setAttribute(QNetworkRequest::User, "PaymentACK"); netRequest.setUrl(QString::fromStdString(details.payment_url())); - netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/bitcoin-payment"); + netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BITCOIN_PAYMENTACK_CONTENTTYPE); netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str()); netRequest.setRawHeader("Accept", BITCOIN_PAYMENTACK_MIMETYPE); @@ -527,7 +533,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien payment.add_transactions(transaction.data(), transaction.size()); // Create a new refund address, or re-use: - QString account = tr("Refund from") + QString(" ") + recipient.authenticatedMerchant; + QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant); std::string strAccount = account.toStdString(); set<CTxDestination> refundAddresses = wallet->GetAccountAddresses(strAccount); if (!refundAddresses.empty()) { @@ -569,11 +575,12 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { - QString message = QObject::tr("Error communicating with %1: %2") + QString msg = tr("Error communicating with %1: %2") .arg(reply->request().url().toString()) .arg(reply->errorString()); - qDebug() << "PaymentServer::netRequestFinished : " << message; - emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL); + + qDebug() << "PaymentServer::netRequestFinished : " << msg; + emit message(tr("Network request error"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -585,12 +592,13 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) PaymentRequestPlus request; QList<SendCoinsRecipient> recipients; if (request.parse(data) && processPaymentRequest(request, recipients)) { - foreach (const SendCoinsRecipient& recipient, recipients){ + foreach (const SendCoinsRecipient& recipient, recipients) { emit receivedPaymentRequest(recipient); } } else qDebug() << "PaymentServer::netRequestFinished : Error processing payment request"; + return; } else if (requestType == "PaymentACK") @@ -598,13 +606,14 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) payments::PaymentACK paymentACK; if (!paymentACK.ParseFromArray(data.data(), data.size())) { - QString message = QObject::tr("Bad response from server %1") + QString msg = tr("Bad response from server %1") .arg(reply->request().url().toString()); - qDebug() << "PaymentServer::netRequestFinished : " << message; - emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL); + + qDebug() << "PaymentServer::netRequestFinished : " << msg; + emit message(tr("Network request error"), msg, CClientUIInterface::MSG_ERROR); } else { - emit receivedPaymentACK(QString::fromStdString(paymentACK.memo())); + emit receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); } } } @@ -618,10 +627,16 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> qDebug() << "PaymentServer::reportSslErrors : " << err; errString += err.errorString() + "\n"; } - emit reportError(tr("Network request error"), errString, CClientUIInterface::MODAL); + emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); } void PaymentServer::setOptionsModel(OptionsModel *optionsModel) { this->optionsModel = optionsModel; } + +void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) +{ + // currently we don't futher process or store the paymentACK message + emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); +} diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index f9d827204b..9f43571edc 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -88,10 +88,10 @@ signals: void receivedPaymentRequest(SendCoinsRecipient); // Fired when a valid PaymentACK is received - void receivedPaymentACK(QString); + void receivedPaymentACK(const QString &paymentACKMsg); - // Fired when an error should be reported to the user - void reportError(QString, QString, unsigned int); + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); public slots: // Signal this when the main window's UI is ready @@ -105,6 +105,7 @@ private slots: void handleURIConnection(); void netRequestFinished(QNetworkReply*); void reportSslErrors(QNetworkReply*, const QList<QSslError> &); + void handlePaymentACK(const QString& paymentACKMsg); private: static bool readPaymentRequest(const QString& filename, PaymentRequestPlus& request); diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp deleted file mode 100644 index 6ddcaaf5d9..0000000000 --- a/src/qt/qrcodedialog.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "qrcodedialog.h" -#include "ui_qrcodedialog.h" - -#include "bitcoinunits.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "optionsmodel.h" - -#include <QPixmap> -#if QT_VERSION < 0x050000 -#include <QUrl> -#endif - -#include <qrencode.h> - -QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) : - QDialog(parent), - ui(new Ui::QRCodeDialog), - model(0), - address(addr) -{ - ui->setupUi(this); - - setWindowTitle(QString("%1").arg(address)); - - ui->chkReqPayment->setVisible(enableReq); - ui->lblAmount->setVisible(enableReq); - ui->lnReqAmount->setVisible(enableReq); - - ui->lnLabel->setText(label); - - ui->btnSaveAs->setEnabled(false); - - genCode(); -} - -QRCodeDialog::~QRCodeDialog() -{ - delete ui; -} - -void QRCodeDialog::setModel(OptionsModel *model) -{ - this->model = model; - - if (model) - connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); - - // update the display unit, to not use the default ("BTC") - updateDisplayUnit(); -} - -void QRCodeDialog::genCode() -{ - QString uri = getURI(); - - if (uri != "") - { - ui->lblQRCode->setText(""); - - QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); - if (!code) - { - ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); - return; - } - myImage = QImage(code->width + 8, code->width + 8, 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 + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); - p++; - } - } - QRcode_free(code); - - ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); - - ui->outUri->setPlainText(uri); - } -} - -QString QRCodeDialog::getURI() -{ - QString ret = QString("bitcoin:%1").arg(address); - int paramCount = 0; - - ui->outUri->clear(); - - if (ui->chkReqPayment->isChecked()) - { - if (ui->lnReqAmount->validate()) - { - // even if we allow a non BTC unit input in lnReqAmount, we generate the URI with BTC as unit (as defined in BIP21) - ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, ui->lnReqAmount->value())); - paramCount++; - } - else - { - ui->btnSaveAs->setEnabled(false); - ui->lblQRCode->setText(tr("The entered amount is invalid, please check.")); - return QString(""); - } - } - - if (!ui->lnLabel->text().isEmpty()) - { - QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text())); - ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl); - paramCount++; - } - - if (!ui->lnMessage->text().isEmpty()) - { - QString msg(QUrl::toPercentEncoding(ui->lnMessage->text())); - ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); - paramCount++; - } - - // limit URI length to prevent a DoS against the QR-Code dialog - if (ret.length() > MAX_URI_LENGTH) - { - ui->btnSaveAs->setEnabled(false); - ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); - return QString(""); - } - - ui->btnSaveAs->setEnabled(true); - return ret; -} - -void QRCodeDialog::on_lnReqAmount_textChanged() -{ - genCode(); -} - -void QRCodeDialog::on_lnLabel_textChanged() -{ - genCode(); -} - -void QRCodeDialog::on_lnMessage_textChanged() -{ - genCode(); -} - -void QRCodeDialog::on_btnSaveAs_clicked() -{ - QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Images (*.png)")); - if (!fn.isEmpty()) - myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn); -} - -void QRCodeDialog::on_chkReqPayment_toggled(bool fChecked) -{ - if (!fChecked) - // if chkReqPayment is not active, don't display lnReqAmount as invalid - ui->lnReqAmount->setValid(true); - - genCode(); -} - -void QRCodeDialog::updateDisplayUnit() -{ - if (model) - { - // Update lnReqAmount with the current unit - ui->lnReqAmount->setDisplayUnit(model->getDisplayUnit()); - } -} diff --git a/src/qt/qrcodedialog.h b/src/qt/qrcodedialog.h deleted file mode 100644 index c55c34bce6..0000000000 --- a/src/qt/qrcodedialog.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QRCODEDIALOG_H -#define QRCODEDIALOG_H - -#include <QDialog> -#include <QImage> - -namespace Ui { - class QRCodeDialog; -} -class OptionsModel; - -class QRCodeDialog : public QDialog -{ - Q_OBJECT - -public: - explicit QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent = 0); - ~QRCodeDialog(); - - void setModel(OptionsModel *model); - -private slots: - void on_lnReqAmount_textChanged(); - void on_lnLabel_textChanged(); - void on_lnMessage_textChanged(); - void on_btnSaveAs_clicked(); - void on_chkReqPayment_toggled(bool fChecked); - - void updateDisplayUnit(); - -private: - Ui::QRCodeDialog *ui; - OptionsModel *model; - QString address; - QImage myImage; - - void genCode(); - QString getURI(); -}; - -#endif // QRCODEDIALOG_H diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp new file mode 100644 index 0000000000..f3ab343fea --- /dev/null +++ b/src/qt/receivecoinsdialog.cpp @@ -0,0 +1,107 @@ +#include "receivecoinsdialog.h" +#include "ui_receivecoinsdialog.h" + +#include "walletmodel.h" +#include "bitcoinunits.h" +#include "addressbookpage.h" +#include "optionsmodel.h" +#include "guiutil.h" +#include "receiverequestdialog.h" +#include "addresstablemodel.h" + +#include <QMessageBox> +#include <QTextDocument> +#include <QScrollBar> + +ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ReceiveCoinsDialog), + model(0) +{ + ui->setupUi(this); + +#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac + ui->clearButton->setIcon(QIcon()); + ui->receiveButton->setIcon(QIcon()); +#endif + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); +} + +void ReceiveCoinsDialog::setModel(WalletModel *model) +{ + this->model = model; + + if(model && model->getOptionsModel()) + { + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + updateDisplayUnit(); + } +} + +ReceiveCoinsDialog::~ReceiveCoinsDialog() +{ + delete ui; +} + +void ReceiveCoinsDialog::clear() +{ + ui->reqAmount->clear(); + ui->reqLabel->setText(""); + ui->reqMessage->setText(""); + ui->reuseAddress->setChecked(false); + updateDisplayUnit(); +} + +void ReceiveCoinsDialog::reject() +{ + clear(); +} + +void ReceiveCoinsDialog::accept() +{ + clear(); +} + +void ReceiveCoinsDialog::updateDisplayUnit() +{ + if(model && model->getOptionsModel()) + { + ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); + } +} + +void ReceiveCoinsDialog::on_receiveButton_clicked() +{ + if(!model || !model->getOptionsModel() || !model->getAddressTableModel()) + return; + + QString address; + QString label = ui->reqLabel->text(); + if(ui->reuseAddress->isChecked()) + { + /* Choose existing receiving address */ + AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this); + dlg.setModel(model->getAddressTableModel()); + if(dlg.exec()) + { + address = dlg.getReturnValue(); + if(label.isEmpty()) /* If no label provided, use the previously used label */ + { + label = model->getAddressTableModel()->labelForAddress(address); + } + } else { + return; + } + } else { + /* Generate new receiving address */ + address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, ""); + } + SendCoinsRecipient info(address, label, + ui->reqAmount->value(), ui->reqMessage->text()); + ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); + dialog->setModel(model->getOptionsModel()); + dialog->setInfo(info); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + clear(); +} diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h new file mode 100644 index 0000000000..8d12e55afe --- /dev/null +++ b/src/qt/receivecoinsdialog.h @@ -0,0 +1,38 @@ +#ifndef RECEIVECOINSDIALOG_H +#define RECEIVECOINSDIALOG_H + +#include <QDialog> +#include <QVariant> + +namespace Ui { + class ReceiveCoinsDialog; +} +class WalletModel; +class OptionsModel; + +/** Dialog for requesting payment of bitcoins */ +class ReceiveCoinsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ReceiveCoinsDialog(QWidget *parent = 0); + ~ReceiveCoinsDialog(); + + void setModel(WalletModel *model); + +public slots: + void clear(); + void reject(); + void accept(); + +private: + Ui::ReceiveCoinsDialog *ui; + WalletModel *model; + +private slots: + void on_receiveButton_clicked(); + void updateDisplayUnit(); +}; + +#endif // RECEIVECOINSDIALOG_H diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp new file mode 100644 index 0000000000..896acfd233 --- /dev/null +++ b/src/qt/receiverequestdialog.cpp @@ -0,0 +1,185 @@ +#include "receiverequestdialog.h" +#include "ui_receiverequestdialog.h" + +#include "bitcoinunits.h" +#include "guiconstants.h" +#include "guiutil.h" +#include "optionsmodel.h" +#include "walletmodel.h" + +#include <QPixmap> +#include <QClipboard> +#include <QMouseEvent> +#include <QDrag> +#include <QMimeData> +#if QT_VERSION < 0x050000 +#include <QUrl> +#endif + +#if defined(HAVE_CONFIG_H) +#include "bitcoin-config.h" /* for USE_QRCODE */ +#endif + +#ifdef USE_QRCODE +#include <qrencode.h> +#endif + +QRImageWidget::QRImageWidget(QWidget *parent): + QLabel(parent) +{ + setContextMenuPolicy(Qt::ActionsContextMenu); + + QAction *saveImageAction = new QAction(tr("&Save Image..."), this); + connect(saveImageAction, SIGNAL(triggered()), this, SLOT(saveImage())); + addAction(saveImageAction); + QAction *copyImageAction = new QAction(tr("&Copy Image"), this); + connect(copyImageAction, SIGNAL(triggered()), this, SLOT(copyImage())); + addAction(copyImageAction); +} + +QImage QRImageWidget::exportImage() +{ + return pixmap()->toImage().scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE); +} + +void QRImageWidget::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + { + event->accept(); + QMimeData *mimeData = new QMimeData; + mimeData->setImageData(exportImage()); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->exec(); + } else { + QLabel::mousePressEvent(event); + } +} + +void QRImageWidget::saveImage() +{ + QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Images (*.png)")); + if (!fn.isEmpty()) + { + exportImage().save(fn); + } +} + +void QRImageWidget::copyImage() +{ + QApplication::clipboard()->setImage(exportImage()); +} + +ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ReceiveRequestDialog), + model(0) +{ + ui->setupUi(this); + +#ifndef USE_QRCODE + ui->btnSaveAs->setVisible(false); + ui->btnCopyImage->setVisible(false); + ui->lblQRCode->setVisible(false); +#endif + + connect(ui->btnSaveAs, SIGNAL(clicked()), ui->lblQRCode, SLOT(saveImage())); + connect(ui->btnCopyImage, SIGNAL(clicked()), ui->lblQRCode, SLOT(copyImage())); +} + +ReceiveRequestDialog::~ReceiveRequestDialog() +{ + delete ui; +} + +void ReceiveRequestDialog::setModel(OptionsModel *model) +{ + this->model = model; + + if (model) + connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); + + // update the display unit if necessary + update(); +} + +void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &info) +{ + this->info = info; + update(); +} + +void ReceiveRequestDialog::update() +{ + if(!model) + return; + QString target = info.label; + if(target.isEmpty()) + target = info.address; + setWindowTitle(tr("Request payment to %1").arg(target)); + + QString uri = GUIUtil::formatBitcoinURI(info); + ui->btnSaveAs->setEnabled(false); + QString html; + html += "<html><font face='verdana, arial, helvetica, sans-serif'>"; + html += "<b>"+tr("Payment information")+"</b><br>"; + html += "<b>"+tr("URI")+"</b>: "; + html += "<a href=\""+uri+"\">" + GUIUtil::HtmlEscape(uri) + "</a><br>"; + html += "<b>"+tr("Address")+"</b>: " + GUIUtil::HtmlEscape(info.address) + "<br>"; + if(info.amount) + html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatWithUnit(model->getDisplayUnit(), info.amount) + "<br>"; + if(!info.label.isEmpty()) + html += "<b>"+tr("Label")+"</b>: " + GUIUtil::HtmlEscape(info.label) + "<br>"; + if(!info.message.isEmpty()) + html += "<b>"+tr("Message")+"</b>: " + GUIUtil::HtmlEscape(info.message) + "<br>"; + ui->outUri->setText(html); + +#ifdef USE_QRCODE + ui->lblQRCode->setText(""); + if(!uri.isEmpty()) + { + // limit URI length + if (uri.length() > MAX_URI_LENGTH) + { + ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); + } else { + QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); + if (!code) + { + ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); + return; + } + QImage myImage = QImage(code->width + 8, code->width + 8, 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 + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); + p++; + } + } + QRcode_free(code); + + ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); + ui->btnSaveAs->setEnabled(true); + } + } +#endif +} + +void ReceiveRequestDialog::on_btnCopyURI_clicked() +{ + QString uri = GUIUtil::formatBitcoinURI(info); + QApplication::clipboard()->setText(uri, QClipboard::Clipboard); + QApplication::clipboard()->setText(uri, QClipboard::Selection); +} + +void ReceiveRequestDialog::on_btnCopyAddress_clicked() +{ + QApplication::clipboard()->setText(info.address, QClipboard::Clipboard); + QApplication::clipboard()->setText(info.address, QClipboard::Selection); +} diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h new file mode 100644 index 0000000000..1beb873dfd --- /dev/null +++ b/src/qt/receiverequestdialog.h @@ -0,0 +1,57 @@ +#ifndef QRCODEDIALOG_H +#define QRCODEDIALOG_H + +#include "walletmodel.h" + +#include <QDialog> +#include <QImage> +#include <QLabel> + +namespace Ui { + class ReceiveRequestDialog; +} +class OptionsModel; + +/* Label widget for QR code. This image can be dragged, dropped, copied and saved + * to disk. + */ +class QRImageWidget : public QLabel +{ + Q_OBJECT + +public: + explicit QRImageWidget(QWidget *parent = 0); + QImage exportImage(); + +public slots: + void saveImage(); + void copyImage(); + +protected: + virtual void mousePressEvent(QMouseEvent *event); +}; + +class ReceiveRequestDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ReceiveRequestDialog(QWidget *parent = 0); + ~ReceiveRequestDialog(); + + void setModel(OptionsModel *model); + void setInfo(const SendCoinsRecipient &info); + +private slots: + void on_btnCopyURI_clicked(); + void on_btnCopyAddress_clicked(); + + void update(); + +private: + Ui::ReceiveRequestDialog *ui; + OptionsModel *model; + SendCoinsRecipient info; +}; + +#endif // QRCODEDIALOG_H diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 8953c36579..e7dcdf62a1 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -22,6 +22,8 @@ const int CONSOLE_HISTORY = 50; const QSize ICON_SIZE(24, 24); +const int INITIAL_TRAFFIC_GRAPH_MINS = 30; + const struct { const char *url; const char *source; @@ -204,6 +206,7 @@ RPCConsole::RPCConsole(QWidget *parent) : ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); startExecutor(); + setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); clear(); } @@ -253,7 +256,8 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event) void RPCConsole::setClientModel(ClientModel *model) { - this->clientModel = model; + clientModel = model; + ui->trafficGraph->setClientModel(model); if(model) { // Keep up to date with client @@ -263,6 +267,9 @@ void RPCConsole::setClientModel(ClientModel *model) setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers()); connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); + connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); + // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientName->setText(model->clientName()); @@ -431,3 +438,49 @@ void RPCConsole::on_showCLOptionsButton_clicked() GUIUtil::HelpMessageBox help; help.exec(); } + +void RPCConsole::on_sldGraphRange_valueChanged(int value) +{ + const int multiplier = 5; // each position on the slider represents 5 min + int mins = value * multiplier; + setTrafficGraphRange(mins); +} + +QString RPCConsole::FormatBytes(quint64 bytes) +{ + if(bytes < 1024) + return QString(tr("%1 B")).arg(bytes); + if(bytes < 1024 * 1024) + return QString(tr("%1 KB")).arg(bytes / 1024); + if(bytes < 1024 * 1024 * 1024) + return QString(tr("%1 MB")).arg(bytes / 1024 / 1024); + + return QString(tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024); +} + +void RPCConsole::setTrafficGraphRange(int mins) +{ + ui->trafficGraph->setGraphRangeMins(mins); + if(mins < 60) { + ui->lblGraphRange->setText(QString(tr("%1 m")).arg(mins)); + } else { + int hours = mins / 60; + int minsLeft = mins % 60; + if(minsLeft == 0) { + ui->lblGraphRange->setText(QString(tr("%1 h")).arg(hours)); + } else { + ui->lblGraphRange->setText(QString(tr("%1 h %2 m")).arg(hours).arg(minsLeft)); + } + } +} + +void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) +{ + ui->lblBytesIn->setText(FormatBytes(totalBytesIn)); + ui->lblBytesOut->setText(FormatBytes(totalBytesOut)); +} + +void RPCConsole::on_btnClearTrafficGraph_clicked() +{ + ui->trafficGraph->clear(); +} diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 3c38b4b8de..af92b55770 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -37,6 +37,12 @@ private slots: void on_openDebugLogfileButton_clicked(); /** display messagebox with program parameters (same as bitcoin-qt --help) */ void on_showCLOptionsButton_clicked(); + /** change the time range of the network traffic graph */ + void on_sldGraphRange_valueChanged(int value); + /** update traffic statistics */ + void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut); + /** clear traffic graph */ + void on_btnClearTrafficGraph_clicked(); public slots: void clear(); @@ -55,6 +61,9 @@ signals: void cmdRequest(const QString &command); private: + static QString FormatBytes(quint64 bytes); + void setTrafficGraphRange(int mins); + Ui::RPCConsole *ui; ClientModel *clientModel; QStringList history; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 00cea463ef..51304bc05c 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -1,14 +1,13 @@ #include "sendcoinsdialog.h" #include "ui_sendcoinsdialog.h" -#include "walletmodel.h" #include "bitcoinunits.h" -#include "addressbookpage.h" #include "optionsmodel.h" #include "sendcoinsentry.h" #include "guiutil.h" #include "askpassphrasedialog.h" #include "base58.h" +#include "ui_interface.h" #include <QMessageBox> #include <QTextDocument> @@ -137,41 +136,9 @@ void SendCoinsDialog::on_sendButton_clicked() // prepare transaction for getting txFee earlier WalletModelTransaction currentTransaction(recipients); WalletModel::SendCoinsReturn prepareStatus = model->prepareTransaction(currentTransaction); - - QString strSendCoins = tr("Send Coins"); - switch(prepareStatus.status) - { - case WalletModel::InvalidAddress: - QMessageBox::warning(this, strSendCoins, - tr("The recipient address is not valid, please recheck.")); - break; - case WalletModel::InvalidAmount: - QMessageBox::warning(this, strSendCoins, - tr("The amount to pay must be larger than 0.")); - break; - case WalletModel::AmountExceedsBalance: - QMessageBox::warning(this, strSendCoins, - tr("The amount exceeds your balance.")); - break; - case WalletModel::AmountWithFeeExceedsBalance: - QMessageBox::warning(this, strSendCoins, - tr("The total exceeds your balance when the %1 transaction fee is included."). - arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee()))); - break; - case WalletModel::DuplicateAddress: - QMessageBox::warning(this, strSendCoins, - tr("Duplicate address found, can only send to each address once per send operation.")); - break; - case WalletModel::TransactionCreationFailed: - QMessageBox::warning(this, strSendCoins, - tr("Error: Transaction creation failed!")); - break; - case WalletModel::TransactionCommitFailed: - case WalletModel::OK: - case WalletModel::Aborted: // User aborted, nothing to do - default: - break; - } + // process prepareStatus and on error generate message shown to user + processSendCoinsReturn(prepareStatus, + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee())); if(prepareStatus.status != WalletModel::OK) { fNewRecipientAllowed = true; @@ -209,19 +176,13 @@ void SendCoinsDialog::on_sendButton_clicked() } // now send the prepared transaction - WalletModel::SendCoinsReturn sendstatus = model->sendCoins(currentTransaction); - switch(sendstatus.status) + WalletModel::SendCoinsReturn sendStatus = model->sendCoins(currentTransaction); + // process sendStatus and on error generate message shown to user + processSendCoinsReturn(sendStatus); + + if (sendStatus.status == WalletModel::OK) { - case WalletModel::TransactionCommitFailed: - QMessageBox::warning(this, strSendCoins, - tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.")); - break; - case WalletModel::OK: accept(); - break; - case WalletModel::Aborted: // User aborted, nothing to do - default: - break; } fNewRecipientAllowed = true; } @@ -357,17 +318,16 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) const payments::PaymentDetails& details = rv.paymentRequest.getDetails(); if (details.has_expires() && (int64)details.expires() < GetTime()) { - QMessageBox::warning(this, strSendCoins, - tr("Payment request expired")); + emit message(strSendCoins, tr("Payment request expired"), + CClientUIInterface::MSG_WARNING); return false; } } else { CBitcoinAddress address(rv.address.toStdString()); if (!address.IsValid()) { - QString strAddress(address.ToString().c_str()); - QMessageBox::warning(this, strSendCoins, - tr("Invalid payment address %1").arg(strAddress)); + emit message(strSendCoins, tr("Invalid payment address %1").arg(rv.address), + CClientUIInterface::MSG_WARNING); return false; } } @@ -391,3 +351,47 @@ void SendCoinsDialog::updateDisplayUnit() { setBalance(model->getBalance(), 0, 0); } + +void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) +{ + QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams; + // Default to a warning message, override if error message is needed + msgParams.second = CClientUIInterface::MSG_WARNING; + + // This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn. + // WalletModel::TransactionCommitFailed is used only in WalletModel::sendCoins() + // all others are used only in WalletModel::prepareTransaction() + switch(sendCoinsReturn.status) + { + case WalletModel::InvalidAddress: + msgParams.first = tr("The recipient address is not valid, please recheck."); + break; + case WalletModel::InvalidAmount: + msgParams.first = tr("The amount to pay must be larger than 0."); + break; + case WalletModel::AmountExceedsBalance: + msgParams.first = tr("The amount exceeds your balance."); + break; + case WalletModel::AmountWithFeeExceedsBalance: + msgParams.first = tr("The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg); + break; + case WalletModel::DuplicateAddress: + msgParams.first = tr("Duplicate address found, can only send to each address once per send operation."); + break; + case WalletModel::TransactionCreationFailed: + msgParams.first = tr("Transaction creation failed!"); + msgParams.second = CClientUIInterface::MSG_ERROR; + break; + case WalletModel::TransactionCommitFailed: + msgParams.first = tr("The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + msgParams.second = CClientUIInterface::MSG_ERROR; + break; + // OK and Aborted are included to prevent a compiler warning. + case WalletModel::OK: + case WalletModel::Aborted: + default: + return; + } + + emit message(tr("Send Coins"), msgParams.first, msgParams.second); +} diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index f4bffedc9b..4e68e26731 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -1,16 +1,17 @@ #ifndef SENDCOINSDIALOG_H #define SENDCOINSDIALOG_H +#include "walletmodel.h" + #include <QDialog> #include <QVariant> +#include <QPair> namespace Ui { class SendCoinsDialog; } -class WalletModel; class SendCoinsEntry; class SendCoinsRecipient; -class OptionsModel; QT_BEGIN_NAMESPACE class QUrl; @@ -48,10 +49,19 @@ private: WalletModel *model; bool fNewRecipientAllowed; + // Process WalletModel::SendCoinsReturn and generate a pair consisting + // of a message and message flags for use in emit message(). + // Additional parameter msgArg can be used via .arg(msgArg). + void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString()); + private slots: void on_sendButton_clicked(); void removeEntry(SendCoinsEntry* entry); void updateDisplayUnit(); + +signals: + // Fired when a message should be reported to the user + void message(const QString &title, const QString &message, unsigned int style); }; #endif // SENDCOINSDIALOG_H diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index ee84f7bc11..2d42ecb568 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -49,7 +49,7 @@ void SendCoinsEntry::on_addressBookButton_clicked() { if(!model) return; - AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this); + AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); dlg.setModel(model->getAddressTableModel()); if(dlg.exec()) { @@ -60,12 +60,7 @@ void SendCoinsEntry::on_addressBookButton_clicked() void SendCoinsEntry::on_payTo_textChanged(const QString &address) { - if(!model) - return; - // Fill in label from address book, if address has an associated label - QString associatedLabel = model->getAddressTableModel()->labelForAddress(address); - if(!associatedLabel.isEmpty()) - ui->addAsLabel->setText(associatedLabel); + updateLabel(address); } void SendCoinsEntry::setModel(WalletModel *model) @@ -85,10 +80,17 @@ void SendCoinsEntry::setRemoveEnabled(bool enabled) void SendCoinsEntry::clear() { + // clear UI elements for insecure payments ui->payTo->clear(); ui->addAsLabel->clear(); ui->payAmount->clear(); + // and the ones for secure payments just to be sure + ui->payTo_s->clear(); + ui->memoTextLabel_s->clear(); + ui->payAmount_s->clear(); + ui->payTo->setFocus(); + // update the display unit, to not use the default ("BTC") updateDisplayUnit(); } @@ -154,17 +156,20 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value) { recipient = value; - ui->payTo->setText(value.address); - ui->addAsLabel->setText(value.label); - ui->payAmount->setValue(value.amount); - - if (!recipient.authenticatedMerchant.isEmpty()) + if (recipient.authenticatedMerchant.isEmpty()) + { + ui->payTo->setText(recipient.address); + ui->addAsLabel->setText(recipient.label); + ui->payAmount->setValue(recipient.amount); + } + else { - const payments::PaymentDetails& details = value.paymentRequest.getDetails(); + const payments::PaymentDetails& details = recipient.paymentRequest.getDetails(); - ui->payTo_s->setText(value.authenticatedMerchant); + ui->payTo_s->setText(recipient.authenticatedMerchant); ui->memoTextLabel_s->setText(QString::fromStdString(details.memo())); - ui->payAmount_s->setValue(value.amount); + ui->payAmount_s->setValue(recipient.amount); + ui->payAmount_s->setReadOnly(true); setCurrentWidget(ui->SendCoinsSecure); } } @@ -194,3 +199,19 @@ void SendCoinsEntry::updateDisplayUnit() ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); } } + +bool SendCoinsEntry::updateLabel(const QString &address) +{ + if(!model) + return false; + + // Fill in label from address book, if address has an associated label + QString associatedLabel = model->getAddressTableModel()->labelForAddress(address); + if(!associatedLabel.isEmpty()) + { + ui->addAsLabel->setText(associatedLabel); + return true; + } + + return false; +} diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index 49e622daf1..66d9752909 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -58,6 +58,8 @@ private: SendCoinsRecipient recipient; Ui::SendCoinsEntry *ui; WalletModel *model; + + bool updateLabel(const QString &address); }; #endif // SENDCOINSENTRY_H diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 1e9c84fe1a..ff3d00b326 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -86,7 +86,7 @@ void SignVerifyMessageDialog::on_addressBookButton_SM_clicked() { if (model && model->getAddressTableModel()) { - AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this); + AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this); dlg.setModel(model->getAddressTableModel()); if (dlg.exec()) { @@ -178,7 +178,7 @@ void SignVerifyMessageDialog::on_addressBookButton_VM_clicked() { if (model && model->getAddressTableModel()) { - AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this); + AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); dlg.setModel(model->getAddressTableModel()); if (dlg.exec()) { diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 7c9bc46c46..07b71a3c9a 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -66,9 +66,8 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) : pixPaint.setFont(QFont(font, 10*fontFactor)); pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText); - // draw testnet string if -testnet is on - if(QApplication::applicationName().contains(QString("-testnet"))) { - // draw copyright stuff + // draw testnet string if testnet is on + if(TestNet()) { QFont boldFont = QFont(font, 10*fontFactor); boldFont.setWeight(QFont::Bold); pixPaint.setFont(boldFont); diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 802d74719e..df4df3154b 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -50,9 +50,8 @@ void URITests::uriTests() QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); - // We currently don't implement the message parameter (ok, yea, we break spec...) uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address")); - QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp new file mode 100644 index 0000000000..d49bc31f3e --- /dev/null +++ b/src/qt/trafficgraphwidget.cpp @@ -0,0 +1,169 @@ +#include "trafficgraphwidget.h" +#include "clientmodel.h" + +#include <QPainter> +#include <QColor> +#include <QTimer> + +#include <cmath> + +#define DESIRED_SAMPLES 800 + +#define XMARGIN 10 +#define YMARGIN 10 + +TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) : + QWidget(parent), + timer(0), + fMax(0.0f), + nMins(0), + vSamplesIn(), + vSamplesOut(), + nLastBytesIn(0), + nLastBytesOut(0), + clientModel(0) +{ + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(updateRates())); +} + +void TrafficGraphWidget::setClientModel(ClientModel *model) +{ + clientModel = model; + if(model) { + nLastBytesIn = model->getTotalBytesRecv(); + nLastBytesOut = model->getTotalBytesSent(); + } +} + +int TrafficGraphWidget::getGraphRangeMins() const +{ + return nMins; +} + +void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples) +{ + int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; + int sampleCount = samples.size(), x = XMARGIN + w, y; + if(sampleCount > 0) { + path.moveTo(x, YMARGIN + h); + for(int i = 0; i < sampleCount; ++i) { + x = XMARGIN + w - w * i / DESIRED_SAMPLES; + y = YMARGIN + h - (int)(h * samples.at(i) / fMax); + path.lineTo(x, y); + } + path.lineTo(x, YMARGIN + h); + } +} + +void TrafficGraphWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.fillRect(rect(), Qt::black); + + if(fMax <= 0.0f) return; + + QColor axisCol(Qt::gray); + int h = height() - YMARGIN * 2; + painter.setPen(axisCol); + painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h); + + // decide what order of magnitude we are + int base = floor(log10(fMax)); + float val = pow(10.0f, base); + + const QString units = tr("KB/s"); + // draw lines + painter.setPen(axisCol); + painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units)); + for(float y = val; y < fMax; y += val) { + int yy = YMARGIN + h - h * y / fMax; + painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy); + } + // if we drew 3 or fewer lines, break them up at the next lower order of magnitude + if(fMax / val <= 3.0f) { + axisCol = axisCol.darker(); + val = pow(10.0f, base - 1); + painter.setPen(axisCol); + painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units)); + int count = 1; + for(float y = val; y < fMax; y += val, count++) { + // don't overwrite lines drawn above + if(count % 10 == 0) + continue; + int yy = YMARGIN + h - h * y / fMax; + painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy); + } + } + + if(!vSamplesIn.empty()) { + QPainterPath p; + paintPath(p, vSamplesIn); + painter.fillPath(p, QColor(0, 255, 0, 128)); + painter.setPen(Qt::green); + painter.drawPath(p); + } + if(!vSamplesOut.empty()) { + QPainterPath p; + paintPath(p, vSamplesOut); + painter.fillPath(p, QColor(255, 0, 0, 128)); + painter.setPen(Qt::red); + painter.drawPath(p); + } +} + +void TrafficGraphWidget::updateRates() +{ + if(!clientModel) return; + + quint64 bytesIn = clientModel->getTotalBytesRecv(), + bytesOut = clientModel->getTotalBytesSent(); + float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval(); + float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval(); + vSamplesIn.push_front(inRate); + vSamplesOut.push_front(outRate); + nLastBytesIn = bytesIn; + nLastBytesOut = bytesOut; + + while(vSamplesIn.size() > DESIRED_SAMPLES) { + vSamplesIn.pop_back(); + } + while(vSamplesOut.size() > DESIRED_SAMPLES) { + vSamplesOut.pop_back(); + } + + float tmax = 0.0f; + foreach(float f, vSamplesIn) { + if(f > tmax) tmax = f; + } + foreach(float f, vSamplesOut) { + if(f > tmax) tmax = f; + } + fMax = tmax; + update(); +} + +void TrafficGraphWidget::setGraphRangeMins(int mins) +{ + nMins = mins; + int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES; + timer->stop(); + timer->setInterval(msecsPerSample); + + clear(); +} + +void TrafficGraphWidget::clear() +{ + timer->stop(); + + vSamplesOut.clear(); + vSamplesIn.clear(); + fMax = 0.0f; + + if(clientModel) { + nLastBytesIn = clientModel->getTotalBytesRecv(); + nLastBytesOut = clientModel->getTotalBytesSent(); + } + timer->start(); +} diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h new file mode 100644 index 0000000000..b31d1d5b0a --- /dev/null +++ b/src/qt/trafficgraphwidget.h @@ -0,0 +1,44 @@ +#ifndef TRAFFICGRAPHWIDGET_H +#define TRAFFICGRAPHWIDGET_H + +#include <QWidget> +#include <QQueue> + +class ClientModel; + +QT_BEGIN_NAMESPACE +class QPaintEvent; +class QTimer; +QT_END_NAMESPACE + +class TrafficGraphWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TrafficGraphWidget(QWidget *parent = 0); + void setClientModel(ClientModel *model); + int getGraphRangeMins() const; + +protected: + void paintEvent(QPaintEvent *); + +public slots: + void updateRates(); + void setGraphRangeMins(int mins); + void clear(); + +private: + void paintPath(QPainterPath &path, QQueue<float> &samples); + + QTimer *timer; + float fMax; + int nMins; + QQueue<float> vSamplesIn; + QQueue<float> vSamplesOut; + quint64 nLastBytesIn; + quint64 nLastBytesOut; + ClientModel *clientModel; +}; + +#endif // TRAFFICGRAPHWIDGET_H diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index e27aa93a4a..63a72c4553 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -17,7 +17,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) if (!IsFinalTx(wtx)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) - return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1); + return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height() + 1); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } @@ -234,7 +234,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u } if (wtx.IsCoinBase()) - strHTML += "<br>" + tr("Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>"; + { + quint32 numBlocksToMaturity = COINBASE_MATURITY + 1; + strHTML += "<br>" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "<br>"; + } // // Debug view diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index ea2c1f0a5c..162908a9a4 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -160,14 +160,14 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) idx); status.confirmed = wtx.IsConfirmed(); status.depth = wtx.GetDepthInMainChain(); - status.cur_num_blocks = nBestHeight; + status.cur_num_blocks = chainActive.Height(); if (!IsFinalTx(wtx)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) { status.status = TransactionStatus::OpenUntilBlock; - status.open_for = wtx.nLockTime - nBestHeight + 1; + status.open_for = wtx.nLockTime - chainActive.Height() + 1; } else { @@ -221,7 +221,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) bool TransactionRecord::statusUpdateNeeded() { - return status.cur_num_blocks != nBestHeight; + return status.cur_num_blocks != chainActive.Height(); } QString TransactionRecord::getTxID() const diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 07f6a62150..6f7a5933ab 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -250,9 +250,9 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status) void TransactionTableModel::updateConfirmations() { - if(nBestHeight != cachedNumBlocks) + if(chainActive.Height() != cachedNumBlocks) { - cachedNumBlocks = nBestHeight; + cachedNumBlocks = chainActive.Height(); // Blocks came in since last poll. // Invalidate status (number of confirmations) and (possibly) description // for all rows. Qt is smart enough to only actually request the data for the diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a43e29c476..89ecf99656 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -11,6 +11,7 @@ #include "editaddressdialog.h" #include "optionsmodel.h" #include "guiutil.h" +#include "ui_interface.h" #include <QScrollBar> #include <QComboBox> @@ -20,7 +21,6 @@ #include <QLineEdit> #include <QTableView> #include <QHeaderView> -#include <QMessageBox> #include <QPoint> #include <QMenu> #include <QLabel> @@ -266,12 +266,12 @@ void TransactionView::changedAmount(const QString &amount) void TransactionView::exportClicked() { // CSV is currently the only supported format - QString filename = GUIUtil::getSaveFileName( - this, - tr("Export Transaction Data"), QString(), - tr("Comma separated file (*.csv)")); + QString filename = GUIUtil::getSaveFileName(this, + tr("Export Transaction History"), QString(), + tr("Comma separated file (*.csv)")); - if (filename.isNull()) return; + if (filename.isNull()) + return; CSVModelWriter writer(filename); @@ -285,10 +285,13 @@ void TransactionView::exportClicked() writer.addColumn(tr("Amount"), 0, TransactionTableModel::FormattedAmountRole); writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole); - if(!writer.write()) - { - QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename), - QMessageBox::Abort, QMessageBox::Abort); + if(!writer.write()) { + emit message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename), + CClientUIInterface::MSG_ERROR); + } + else { + emit message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename), + CClientUIInterface::MSG_INFORMATION); } } diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index bb41a83e32..464ba3e8ce 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -71,6 +71,9 @@ private slots: 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); + public slots: void chooseDate(int idx); void chooseType(int idx); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 8d6a1b387e..d2807f465a 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -5,20 +5,21 @@ * The Bitcoin Developers 2011-2013 */ #include "walletframe.h" +#include "walletview.h" #include "bitcoingui.h" -#include "walletstack.h" #include <QHBoxLayout> #include <QMessageBox> +#include <QStackedWidget> WalletFrame::WalletFrame(BitcoinGUI *_gui) : - QFrame(_gui) + QFrame(_gui), + gui(_gui) { // Leave HBox hook for adding a list view later QHBoxLayout *walletFrameLayout = new QHBoxLayout(this); setContentsMargins(0,0,0,0); - walletStack = new WalletStack(this); - walletStack->setBitcoinGUI(_gui); + walletStack = new QStackedWidget(this); walletFrameLayout->setContentsMargins(0,0,0,0); walletFrameLayout->addWidget(walletStack); } @@ -29,95 +30,157 @@ WalletFrame::~WalletFrame() void WalletFrame::setClientModel(ClientModel *clientModel) { - if (clientModel) - walletStack->setClientModel(clientModel); + this->clientModel = clientModel; } bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) { - return walletStack->addWallet(name, walletModel); + if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0) + return false; + + WalletView *walletView = new WalletView(this); + walletView->setBitcoinGUI(gui); + walletView->setClientModel(clientModel); + walletView->setWalletModel(walletModel); + walletView->showOutOfSyncWarning(bOutOfSync); + + /* TODO we should goto the currently selected page once dynamically adding wallets is supported */ + walletView->gotoOverviewPage(); + walletStack->addWidget(walletView); + mapWalletViews[name] = walletView; + + // Ensure a walletView is able to show the main window + connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized())); + + return true; } bool WalletFrame::setCurrentWallet(const QString& name) { - // TODO: Check if valid name - return walletStack->setCurrentWallet(name); + if (mapWalletViews.count(name) == 0) + return false; + + WalletView *walletView = mapWalletViews.value(name); + walletStack->setCurrentWidget(walletView); + walletView->updateEncryptionStatus(); + return true; +} + +bool WalletFrame::removeWallet(const QString &name) +{ + if (mapWalletViews.count(name) == 0) + return false; + + WalletView *walletView = mapWalletViews.take(name); + walletStack->removeWidget(walletView); + return true; } void WalletFrame::removeAllWallets() { - walletStack->removeAllWallets(); + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + walletStack->removeWidget(i.value()); + mapWalletViews.clear(); } bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient) { - return walletStack->handlePaymentRequest(recipient); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (!walletView) + return false; + + return walletView->handlePaymentRequest(recipient); } void WalletFrame::showOutOfSyncWarning(bool fShow) { - if (!walletStack) - return; - - walletStack->showOutOfSyncWarning(fShow); + bOutOfSync = fShow; + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->showOutOfSyncWarning(fShow); } void WalletFrame::gotoOverviewPage() { - walletStack->gotoOverviewPage(); + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoOverviewPage(); } void WalletFrame::gotoHistoryPage() { - walletStack->gotoHistoryPage(); -} - -void WalletFrame::gotoAddressBookPage() -{ - walletStack->gotoAddressBookPage(); + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoHistoryPage(); } void WalletFrame::gotoReceiveCoinsPage() { - walletStack->gotoReceiveCoinsPage(); + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoReceiveCoinsPage(); } void WalletFrame::gotoSendCoinsPage(QString addr) { - walletStack->gotoSendCoinsPage(addr); + QMap<QString, WalletView*>::const_iterator i; + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) + i.value()->gotoSendCoinsPage(addr); } void WalletFrame::gotoSignMessageTab(QString addr) { - walletStack->gotoSignMessageTab(addr); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->gotoSignMessageTab(addr); } void WalletFrame::gotoVerifyMessageTab(QString addr) { - walletStack->gotoSignMessageTab(addr); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->gotoVerifyMessageTab(addr); } void WalletFrame::encryptWallet(bool status) { - walletStack->encryptWallet(status); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->encryptWallet(status); } void WalletFrame::backupWallet() { - walletStack->backupWallet(); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->backupWallet(); } void WalletFrame::changePassphrase() { - walletStack->changePassphrase(); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->changePassphrase(); } void WalletFrame::unlockWallet() { - walletStack->unlockWallet(); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->unlockWallet(); +} + +void WalletFrame::usedSendingAddresses() +{ + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->usedSendingAddresses(); } -void WalletFrame::setEncryptionStatus() +void WalletFrame::usedReceivingAddresses() { - walletStack->setEncryptionStatus(); + WalletView *walletView = (WalletView*)walletStack->currentWidget(); + if (walletView) + walletView->usedReceivingAddresses(); } diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index eaae053ccd..edf2390dbc 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -8,12 +8,17 @@ #define WALLETFRAME_H #include <QFrame> +#include <QMap> class BitcoinGUI; class ClientModel; class SendCoinsRecipient; class WalletModel; -class WalletStack; +class WalletView; + +QT_BEGIN_NAMESPACE +class QStackedWidget; +QT_END_NAMESPACE class WalletFrame : public QFrame { @@ -27,7 +32,7 @@ public: bool addWallet(const QString& name, WalletModel *walletModel); bool setCurrentWallet(const QString& name); - + bool removeWallet(const QString &name); void removeAllWallets(); bool handlePaymentRequest(const SendCoinsRecipient& recipient); @@ -35,15 +40,18 @@ public: void showOutOfSyncWarning(bool fShow); private: - WalletStack *walletStack; + QStackedWidget *walletStack; + BitcoinGUI *gui; + ClientModel *clientModel; + QMap<QString, WalletView*> mapWalletViews; + + bool bOutOfSync; public slots: /** Switch to overview (home) page */ void gotoOverviewPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); - /** Switch to address book page */ - void gotoAddressBookPage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); /** Switch to send coins page */ @@ -63,11 +71,10 @@ public slots: /** Ask for passphrase to unlock wallet temporarily */ void unlockWallet(); - /** Set the encryption status as shown in the UI. - @param[in] status current encryption status - @see WalletModel::EncryptionStatus - */ - void setEncryptionStatus(); + /** Show used sending addresses */ + void usedSendingAddresses(); + /** Show used receiving addresses */ + void usedReceivingAddresses(); }; #endif // WALLETFRAME_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index bda39b675f..417bac9928 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -73,10 +73,10 @@ void WalletModel::updateStatus() void WalletModel::pollBalanceChanged() { - if(nBestHeight != cachedNumBlocks) + if(chainActive.Height() != cachedNumBlocks) { // Balance and number of transactions might have changed - cachedNumBlocks = nBestHeight; + cachedNumBlocks = chainActive.Height(); checkBalanceChanged(); } } @@ -258,22 +258,26 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran // and emit coinsSent signal for each recipient foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) { - std::string strAddress = rcp.address.toStdString(); - CTxDestination dest = CBitcoinAddress(strAddress).Get(); - std::string strLabel = rcp.label.toStdString(); + // Don't touch the address book when we have a secure payment-request + if (rcp.authenticatedMerchant.isEmpty()) { - LOCK(wallet->cs_wallet); - - std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest); - - // Check if we have a new address or an updated label - if (mi == wallet->mapAddressBook.end()) - { - wallet->SetAddressBook(dest, strLabel, "send"); - } - else if (mi->second.name != strLabel) + std::string strAddress = rcp.address.toStdString(); + CTxDestination dest = CBitcoinAddress(strAddress).Get(); + std::string strLabel = rcp.label.toStdString(); { - wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose + LOCK(wallet->cs_wallet); + + std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest); + + // Check if we have a new address or an updated label + if (mi == wallet->mapAddressBook.end()) + { + wallet->SetAddressBook(dest, strLabel, "send"); + } + else if (mi->second.name != strLabel) + { + wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose + } } } emit coinsSent(wallet, rcp, transaction_array); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 6abcdaf8cb..2e99eaddcb 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -21,11 +21,14 @@ QT_END_NAMESPACE class SendCoinsRecipient { public: - SendCoinsRecipient() : amount(0) { } + explicit SendCoinsRecipient() : amount(0) { } + explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message): + address(addr), label(label), amount(amount), message(message) {} QString address; QString label; qint64 amount; + QString message; // If from a payment request, paymentRequest.IsInitialized() will be true PaymentRequestPlus paymentRequest; diff --git a/src/qt/walletstack.cpp b/src/qt/walletstack.cpp deleted file mode 100644 index 4ef87aed52..0000000000 --- a/src/qt/walletstack.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Qt4 bitcoin GUI. - * - * W.J. van der Laan 2011-2012 - * The Bitcoin Developers 2011-2013 - */ -#include "walletstack.h" -#include "walletview.h" -#include "bitcoingui.h" - -#include <QMap> -#include <QMessageBox> - -WalletStack::WalletStack(QWidget *parent) : - QStackedWidget(parent), - gui(0), - clientModel(0), - bOutOfSync(true) -{ - setContentsMargins(0,0,0,0); -} - -WalletStack::~WalletStack() -{ -} - -bool WalletStack::addWallet(const QString& name, WalletModel *walletModel) -{ - if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0) - return false; - - WalletView *walletView = new WalletView(this, gui); - walletView->setBitcoinGUI(gui); - walletView->setClientModel(clientModel); - walletView->setWalletModel(walletModel); - walletView->showOutOfSyncWarning(bOutOfSync); - addWidget(walletView); - mapWalletViews[name] = walletView; - - // Ensure a walletView is able to show the main window - connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized())); - - return true; -} - -bool WalletStack::removeWallet(const QString& name) -{ - if (mapWalletViews.count(name) == 0) - return false; - - WalletView *walletView = mapWalletViews.take(name); - removeWidget(walletView); - return true; -} - -void WalletStack::removeAllWallets() -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - removeWidget(i.value()); - mapWalletViews.clear(); -} - -bool WalletStack::handlePaymentRequest(const SendCoinsRecipient &recipient) -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (!walletView) - return false; - - return walletView->handlePaymentRequest(recipient); -} - -void WalletStack::showOutOfSyncWarning(bool fShow) -{ - bOutOfSync = fShow; - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->showOutOfSyncWarning(fShow); -} - -void WalletStack::gotoOverviewPage() -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoOverviewPage(); -} - -void WalletStack::gotoHistoryPage() -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoHistoryPage(); -} - -void WalletStack::gotoAddressBookPage() -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoAddressBookPage(); -} - -void WalletStack::gotoReceiveCoinsPage() -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoReceiveCoinsPage(); -} - -void WalletStack::gotoSendCoinsPage(QString addr) -{ - QMap<QString, WalletView*>::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoSendCoinsPage(addr); -} - -void WalletStack::gotoSignMessageTab(QString addr) -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->gotoSignMessageTab(addr); -} - -void WalletStack::gotoVerifyMessageTab(QString addr) -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->gotoVerifyMessageTab(addr); -} - -void WalletStack::encryptWallet(bool status) -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->encryptWallet(status); -} - -void WalletStack::backupWallet() -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->backupWallet(); -} - -void WalletStack::changePassphrase() -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->changePassphrase(); -} - -void WalletStack::unlockWallet() -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->unlockWallet(); -} - -void WalletStack::setEncryptionStatus() -{ - WalletView *walletView = (WalletView*)currentWidget(); - if (walletView) - walletView->setEncryptionStatus(); -} - -bool WalletStack::setCurrentWallet(const QString& name) -{ - if (mapWalletViews.count(name) == 0) - return false; - - WalletView *walletView = mapWalletViews.value(name); - setCurrentWidget(walletView); - walletView->setEncryptionStatus(); - return true; -} diff --git a/src/qt/walletstack.h b/src/qt/walletstack.h deleted file mode 100644 index 74b9f09081..0000000000 --- a/src/qt/walletstack.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Qt4 bitcoin GUI. - * - * W.J. van der Laan 2011-2012 - * The Bitcoin Developers 2011-2013 - */ -#ifndef WALLETSTACK_H -#define WALLETSTACK_H - -#include <QStackedWidget> -#include <QMap> -#include <boost/shared_ptr.hpp> - -class BitcoinGUI; -class TransactionTableModel; -class ClientModel; -class WalletModel; -class WalletView; -class TransactionView; -class OverviewPage; -class AddressBookPage; -class SendCoinsDialog; -class SendCoinsRecipient; -class SignVerifyMessageDialog; -class Notificator; -class RPCConsole; - -class CWalletManager; - -QT_BEGIN_NAMESPACE -class QLabel; -class QModelIndex; -QT_END_NAMESPACE - -/* - WalletStack class. This class is a container for WalletView instances. It takes the place of centralWidget. - It was added to support multiple wallet functionality. It communicates with both the client and the - wallet models to give the user an up-to-date view of the current core state. It manages all the wallet views - it contains and updates them accordingly. - */ -class WalletStack : public QStackedWidget -{ - Q_OBJECT - -public: - explicit WalletStack(QWidget *parent = 0); - ~WalletStack(); - - void setBitcoinGUI(BitcoinGUI *gui) { this->gui = gui; } - - void setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; } - - bool addWallet(const QString& name, WalletModel *walletModel); - bool removeWallet(const QString& name); - - void removeAllWallets(); - - bool handlePaymentRequest(const SendCoinsRecipient &recipient); - - void showOutOfSyncWarning(bool fShow); - -private: - BitcoinGUI *gui; - ClientModel *clientModel; - QMap<QString, WalletView*> mapWalletViews; - - bool bOutOfSync; - -public slots: - bool setCurrentWallet(const QString& name); - - /** Switch to overview (home) page */ - void gotoOverviewPage(); - /** Switch to history (transactions) page */ - void gotoHistoryPage(); - /** Switch to address book page */ - void gotoAddressBookPage(); - /** Switch to receive coins page */ - void gotoReceiveCoinsPage(); - /** Switch to send coins page */ - void gotoSendCoinsPage(QString addr = ""); - - /** 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 */ - void gotoVerifyMessageTab(QString addr = ""); - - /** Encrypt the wallet */ - void encryptWallet(bool status); - /** Backup the wallet */ - void backupWallet(); - /** Change encrypted wallet passphrase */ - void changePassphrase(); - /** Ask for passphrase to unlock wallet temporarily */ - void unlockWallet(); - - /** Set the encryption status as shown in the UI. - @param[in] status current encryption status - @see WalletModel::EncryptionStatus - */ - void setEncryptionStatus(); -}; - -#endif // WALLETSTACK_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index efb74efaa0..d1e5e47bd5 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -9,6 +9,7 @@ #include "transactiontablemodel.h" #include "addressbookpage.h" #include "sendcoinsdialog.h" +#include "receivecoinsdialog.h" #include "signverifymessagedialog.h" #include "clientmodel.h" #include "walletmodel.h" @@ -17,21 +18,15 @@ #include "overviewpage.h" #include "askpassphrasedialog.h" #include "ui_interface.h" +#include "guiutil.h" #include <QHBoxLayout> #include <QVBoxLayout> #include <QAction> -#if QT_VERSION < 0x050000 -#include <QDesktopServices> -#else -#include <QStandardPaths> -#endif -#include <QFileDialog> #include <QPushButton> -WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui): +WalletView::WalletView(QWidget *parent): QStackedWidget(parent), - gui(_gui), clientModel(0), walletModel(0) { @@ -53,37 +48,27 @@ WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui): vbox->addLayout(hbox_buttons); transactionsPage->setLayout(vbox); - addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab); - - receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab); - - sendCoinsPage = new SendCoinsDialog(gui); - - signVerifyMessageDialog = new SignVerifyMessageDialog(gui); + receiveCoinsPage = new ReceiveCoinsDialog(); + sendCoinsPage = new SendCoinsDialog(); addWidget(overviewPage); addWidget(transactionsPage); - addWidget(addressBookPage); addWidget(receiveCoinsPage); addWidget(sendCoinsPage); - // Clicking on a transaction on the overview page simply sends you to transaction history page - connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage())); + // 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))); // Double-clicking on a transaction on the transaction history page shows details connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); - // Clicking on "Send Coins" in the address book sends you to the send coins tab - connect(addressBookPage, SIGNAL(sendCoins(QString)), this, SLOT(gotoSendCoinsPage(QString))); - // Clicking on "Verify Message" in the address book opens the verify message tab in the Sign/Verify Message dialog - connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString))); - // Clicking on "Sign Message" in the receive coins page opens the sign message tab in the Sign/Verify Message dialog - connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString))); // Clicking on "Export" allows to export the transaction list connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked())); - gotoOverviewPage(); + // Pass through messages from sendCoinsPage + connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); + // Pass through messages from transactionView + connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); } WalletView::~WalletView() @@ -92,49 +77,58 @@ WalletView::~WalletView() void WalletView::setBitcoinGUI(BitcoinGUI *gui) { - this->gui = gui; + if (gui) + { + // Clicking on a transaction on the overview page simply sends you to transaction history page + connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage())); + + // Receive and report messages + connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int))); + + // Pass through encryption status changed signals + connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int))); + + // Pass through transaction notifications + connect(this, SIGNAL(incomingTransaction(QString,int,qint64,QString,QString)), gui, SLOT(incomingTransaction(QString,int,qint64,QString,QString))); + } } void WalletView::setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; - if (clientModel) - { - overviewPage->setClientModel(clientModel); - addressBookPage->setOptionsModel(clientModel->getOptionsModel()); - receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel()); - } + + overviewPage->setClientModel(clientModel); } void WalletView::setWalletModel(WalletModel *walletModel) { this->walletModel = walletModel; + + // Put transaction list in tabs + transactionView->setModel(walletModel); + overviewPage->setWalletModel(walletModel); + receiveCoinsPage->setModel(walletModel); + sendCoinsPage->setModel(walletModel); + if (walletModel) { - // Receive and report messages from wallet thread - connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int))); - - // Put transaction list in tabs - transactionView->setModel(walletModel); - overviewPage->setWalletModel(walletModel); - addressBookPage->setModel(walletModel->getAddressTableModel()); - receiveCoinsPage->setModel(walletModel->getAddressTableModel()); - sendCoinsPage->setModel(walletModel); - signVerifyMessageDialog->setModel(walletModel); + // Receive and pass through messages from wallet model + connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); - setEncryptionStatus(); - connect(walletModel, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int))); + // Handle changes in encryption status + connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); + updateEncryptionStatus(); // Balloon pop-up for new transaction connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(incomingTransaction(QModelIndex,int,int))); + this, SLOT(processNewTransaction(QModelIndex,int,int))); // Ask for passphrase if needed connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); } } -void WalletView::incomingTransaction(const QModelIndex& parent, int start, int /*end*/) +void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/) { // Prevent balloon-spam when initial block download is in progress if (!walletModel || !clientModel || clientModel->inInitialBlockDownload()) @@ -147,36 +141,26 @@ void WalletView::incomingTransaction(const QModelIndex& parent, int start, int / QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString(); QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString(); - gui->incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address); + emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address); } void WalletView::gotoOverviewPage() { - gui->getOverviewAction()->setChecked(true); setCurrentWidget(overviewPage); } void WalletView::gotoHistoryPage() { - gui->getHistoryAction()->setChecked(true); setCurrentWidget(transactionsPage); } -void WalletView::gotoAddressBookPage() -{ - gui->getAddressBookAction()->setChecked(true); - setCurrentWidget(addressBookPage); -} - void WalletView::gotoReceiveCoinsPage() { - gui->getReceiveCoinsAction()->setChecked(true); setCurrentWidget(receiveCoinsPage); } void WalletView::gotoSendCoinsPage(QString addr) { - gui->getSendCoinsAction()->setChecked(true); setCurrentWidget(sendCoinsPage); if (!addr.isEmpty()) @@ -185,7 +169,10 @@ void WalletView::gotoSendCoinsPage(QString addr) void WalletView::gotoSignMessageTab(QString addr) { - // call show() in showTab_SM() + // calls show() in showTab_SM() + SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this); + signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose); + signVerifyMessageDialog->setModel(walletModel); signVerifyMessageDialog->showTab_SM(true); if (!addr.isEmpty()) @@ -194,7 +181,10 @@ void WalletView::gotoSignMessageTab(QString addr) void WalletView::gotoVerifyMessageTab(QString addr) { - // call show() in showTab_VM() + // calls show() in showTab_VM() + SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this); + signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose); + signVerifyMessageDialog->setModel(walletModel); signVerifyMessageDialog->showTab_VM(true); if (!addr.isEmpty()) @@ -203,15 +193,7 @@ void WalletView::gotoVerifyMessageTab(QString addr) bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient) { - // URI has to be valid - if (sendCoinsPage->handlePaymentRequest(recipient)) - { - gotoSendCoinsPage(); - emit showNormalIfMinimized(); - return true; - } - else - return false; + return sendCoinsPage->handlePaymentRequest(recipient); } void WalletView::showOutOfSyncWarning(bool fShow) @@ -219,9 +201,9 @@ void WalletView::showOutOfSyncWarning(bool fShow) overviewPage->showOutOfSyncWarning(fShow); } -void WalletView::setEncryptionStatus() +void WalletView::updateEncryptionStatus() { - gui->setEncryptionStatus(walletModel->getEncryptionStatus()); + emit encryptionStatusChanged(walletModel->getEncryptionStatus()); } void WalletView::encryptWallet(bool status) @@ -232,25 +214,25 @@ void WalletView::encryptWallet(bool status) dlg.setModel(walletModel); dlg.exec(); - setEncryptionStatus(); + updateEncryptionStatus(); } void WalletView::backupWallet() { -#if QT_VERSION < 0x050000 - QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); -#else - QString saveDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); -#endif - QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)")); - if (!filename.isEmpty()) { - if (!walletModel->backupWallet(filename)) { - gui->message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."), - CClientUIInterface::MSG_ERROR); + QString filename = GUIUtil::getSaveFileName(this, + tr("Backup Wallet"), QString(), + tr("Wallet Data (*.dat)")); + + if (filename.isEmpty()) + return; + + if (!walletModel->backupWallet(filename)) { + emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename), + CClientUIInterface::MSG_ERROR); } - else - gui->message(tr("Backup Successful"), tr("The wallet data was successfully saved to the new location."), - CClientUIInterface::MSG_INFORMATION); + else { + emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename), + CClientUIInterface::MSG_INFORMATION); } } @@ -273,3 +255,23 @@ void WalletView::unlockWallet() dlg.exec(); } } + +void WalletView::usedSendingAddresses() +{ + if(!walletModel) + return; + AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this); + dlg->setModel(walletModel->getAddressTableModel()); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); +} + +void WalletView::usedReceivingAddresses() +{ + if(!walletModel) + return; + AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this); + dlg->setModel(walletModel->getAddressTableModel()); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); +} diff --git a/src/qt/walletview.h b/src/qt/walletview.h index ce4e051098..61515047ca 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -14,8 +14,8 @@ class ClientModel; class WalletModel; class TransactionView; class OverviewPage; -class AddressBookPage; class SendCoinsDialog; +class ReceiveCoinsDialog; class SendCoinsRecipient; class SignVerifyMessageDialog; class RPCConsole; @@ -36,7 +36,7 @@ class WalletView : public QStackedWidget Q_OBJECT public: - explicit WalletView(QWidget *parent, BitcoinGUI *_gui); + explicit WalletView(QWidget *parent); ~WalletView(); void setBitcoinGUI(BitcoinGUI *gui); @@ -55,16 +55,13 @@ public: void showOutOfSyncWarning(bool fShow); private: - BitcoinGUI *gui; ClientModel *clientModel; WalletModel *walletModel; OverviewPage *overviewPage; QWidget *transactionsPage; - AddressBookPage *addressBookPage; - AddressBookPage *receiveCoinsPage; + ReceiveCoinsDialog *receiveCoinsPage; SendCoinsDialog *sendCoinsPage; - SignVerifyMessageDialog *signVerifyMessageDialog; TransactionView *transactionView; @@ -73,8 +70,6 @@ public slots: void gotoOverviewPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); - /** Switch to address book page */ - void gotoAddressBookPage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); /** Switch to send coins page */ @@ -89,7 +84,7 @@ public slots: The new items are those between start and end inclusive, under the given parent item. */ - void incomingTransaction(const QModelIndex& parent, int start, int /*end*/); + void processNewTransaction(const QModelIndex& parent, int start, int /*end*/); /** Encrypt the wallet */ void encryptWallet(bool status); /** Backup the wallet */ @@ -99,11 +94,22 @@ public slots: /** Ask for passphrase to unlock wallet temporarily */ void unlockWallet(); - void setEncryptionStatus(); + /** Show used sending addresses */ + void usedSendingAddresses(); + /** Show used receiving addresses */ + void usedReceivingAddresses(); + /** Re-emit encryption status signal */ + void updateEncryptionStatus(); signals: /** Signal that we want to show the main window */ void showNormalIfMinimized(); + /** Fired when a message should be reported to the user */ + void message(const QString &title, const QString &message, unsigned int style); + /** Encryption status of wallet changed */ + void encryptionStatusChanged(int status); + /** Notify that a new transaction appeared */ + void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); }; #endif // WALLETVIEW_H |