diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bitcoinrpc.cpp | 2 | ||||
-rw-r--r-- | src/init.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 8 | ||||
-rw-r--r-- | src/main.h | 1 | ||||
-rw-r--r-- | src/qt/addressbookpage.cpp | 22 | ||||
-rw-r--r-- | src/qt/addressbookpage.h | 1 | ||||
-rw-r--r-- | src/qt/bitcoin.cpp | 55 | ||||
-rw-r--r-- | src/qt/bitcoingui.cpp | 54 | ||||
-rw-r--r-- | src/qt/bitcoingui.h | 7 | ||||
-rw-r--r-- | src/qt/forms/addressbookpage.ui | 14 | ||||
-rw-r--r-- | src/qt/forms/messagepage.ui | 170 | ||||
-rw-r--r-- | src/qt/messagepage.cpp | 107 | ||||
-rw-r--r-- | src/qt/messagepage.h | 38 | ||||
-rw-r--r-- | src/qt/qtipcserver.cpp | 95 | ||||
-rw-r--r-- | src/qt/qtipcserver.h | 2 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 17 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.h | 1 | ||||
-rw-r--r-- | src/qt/sendcoinsentry.cpp | 5 | ||||
-rw-r--r-- | src/qt/sendcoinsentry.h | 2 | ||||
-rw-r--r-- | src/qtui.h | 1 |
20 files changed, 599 insertions, 5 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 3063abd1fa..03c01f7b21 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -589,8 +589,6 @@ Value sendtoaddress(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } -static const string strMessageMagic = "Bitcoin Signed Message:\n"; - Value signmessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) diff --git a/src/init.cpp b/src/init.cpp index 837d73f959..d237e247e7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -273,7 +273,7 @@ bool AppInit2(int argc, char* argv[]) #ifndef QT_GUI for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0])) + if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)) fCommandLine = true; if (fCommandLine) diff --git a/src/main.cpp b/src/main.cpp index 1dbd50f4e6..5981c675a1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,6 +53,9 @@ map<uint256, CDataStream*> mapOrphanTransactions; multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev; +const string strMessageMagic = "Bitcoin Signed Message:\n"; + + double dHashesPerSec; int64 nHPSTimerStart; @@ -3070,8 +3073,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) if (!tx.FetchInputs(txdb, mapTestPoolTmp, false, true, mapInputs, fInvalid)) continue; - int64 nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); - if (nFees < nMinFee) + int64 nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); + if (nTxFees < nMinFee) continue; nTxSigOps += tx.GetP2SHSigOpCount(mapInputs); @@ -3088,6 +3091,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) nBlockSize += nTxSize; ++nBlockTx; nBlockSigOps += nTxSigOps; + nFees += nTxFees; // Add transactions that depend on this one to the priority queue uint256 hash = tx.GetHash(); diff --git a/src/main.h b/src/main.h index 124b228ec9..825c81e485 100644 --- a/src/main.h +++ b/src/main.h @@ -72,6 +72,7 @@ extern uint64 nPooledTx; extern unsigned int nTransactionsUpdated; extern uint64 nLastBlockTx; extern uint64 nLastBlockSize; +extern const std::string strMessageMagic; extern double dHashesPerSec; extern int64 nHPSTimerStart; extern int64 nTimeBestReceived; diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 91412fcc18..b5a798ca31 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -2,6 +2,7 @@ #include "ui_addressbookpage.h" #include "addresstablemodel.h" +#include "bitcoingui.h" #include "editaddressdialog.h" #include "csvmodelwriter.h" #include "guiutil.h" @@ -156,6 +157,24 @@ void AddressBookPage::onEditAction() dlg.exec(); } +void AddressBookPage::on_signMessage_clicked() +{ + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + QString addr; + + foreach (QModelIndex index, indexes) + { + QVariant address = index.data(); + addr = address.toString(); + } + + QObject *qoGUI = parent()->parent(); + BitcoinGUI *gui = qobject_cast<BitcoinGUI *>(qoGUI); + if (gui) + gui->gotoMessagePage(addr); +} + void AddressBookPage::on_newAddressButton_clicked() { if(!model) @@ -207,11 +226,13 @@ void AddressBookPage::selectionChanged() // In sending tab, allow deletion of selection ui->deleteButton->setEnabled(true); deleteAction->setEnabled(true); + ui->signMessage->setEnabled(false); break; case ReceivingTab: // Deleting receiving addresses, however, is not allowed ui->deleteButton->setEnabled(false); deleteAction->setEnabled(false); + ui->signMessage->setEnabled(true); break; } ui->copyToClipboard->setEnabled(true); @@ -222,6 +243,7 @@ void AddressBookPage::selectionChanged() ui->deleteButton->setEnabled(false); ui->showQRCode->setEnabled(false); ui->copyToClipboard->setEnabled(false); + ui->signMessage->setEnabled(false); } } diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 6b08f8415b..b2cf2db979 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -57,6 +57,7 @@ private slots: void on_newAddressButton_clicked(); /** Copy address of currently selected address entry to clipboard */ void on_copyToClipboard_clicked(); + void on_signMessage_clicked(); void selectionChanged(); void on_showQRCode_clicked(); /** Spawn contextual menu (right mouse menu) for address book entry */ diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 894bbb9d1e..85ece9e2ce 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -8,6 +8,7 @@ #include "headers.h" #include "init.h" +#include "qtipcserver.h" #include <QApplication> #include <QMessageBox> @@ -18,6 +19,8 @@ #include <QSplashScreen> #include <QLibraryInfo> +#include <boost/interprocess/ipc/message_queue.hpp> + // Need a global reference for the notifications to find the GUI BitcoinGUI *guiref; QSplashScreen *splashref; @@ -79,6 +82,22 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindo return payFee; } +void ThreadSafeHandleURL(const std::string& strURL) +{ + if(!guiref) + return; + + // Call slot on GUI thread. + // If called from another thread, use a blocking QueuedConnection. + Qt::ConnectionType connectionType = Qt::DirectConnection; + if(QThread::currentThread() != QCoreApplication::instance()->thread()) + { + connectionType = Qt::BlockingQueuedConnection; + } + QMetaObject::invokeMethod(guiref, "handleURL", connectionType, + Q_ARG(QString, QString::fromStdString(strURL))); +} + void CalledSetStatusBar(const std::string& strText, int nField) { // Only used for built-in mining, which is disabled, simple ignore @@ -114,6 +133,25 @@ std::string _(const char* psz) int main(int argc, char *argv[]) { + // Do this early as we don't want to bother initializing if we are just calling IPC + for (int i = 1; i < argc; i++) + { + if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0) + { + const char *strURL = argv[i]; + try { + boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL"); + if(mq.try_send(strURL, strlen(strURL), 0)) + exit(0); + else + break; + } + catch (boost::interprocess::interprocess_exception &ex) { + break; + } + } + } + // Internal string conversion is all UTF-8 QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForTr()); @@ -185,6 +223,23 @@ int main(int argc, char *argv[]) window.show(); } + // Place this here as guiref has to be defined if we dont want to lose URLs + ipcInit(); + // Check for URL in argv + for (int i = 1; i < argc; i++) + { + if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0) + { + const char *strURL = argv[i]; + try { + boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL"); + mq.try_send(strURL, strlen(strURL), 0); + } + catch (boost::interprocess::interprocess_exception &ex) { + } + } + } + app.exec(); guiref = 0; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index d77279d42b..3e0a12b9cf 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -8,6 +8,7 @@ #include "transactiontablemodel.h" #include "addressbookpage.h" #include "sendcoinsdialog.h" +#include "messagepage.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" @@ -99,12 +100,17 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): sendCoinsPage = new SendCoinsDialog(this); + messagePage = new MessagePage(this); + centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); centralWidget->addWidget(transactionsPage); centralWidget->addWidget(addressBookPage); centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); +#ifdef FIRST_CLASS_MESSAGING + centralWidget->addWidget(messagePage); +#endif setCentralWidget(centralWidget); // Create status bar @@ -192,6 +198,13 @@ void BitcoinGUI::createActions() sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); + messageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message"), this); + messageAction->setToolTip(tr("Prove you control an address")); +#ifdef FIRST_CLASS_MESSAGING + messageAction->setCheckable(true); +#endif + tabGroup->addAction(messageAction); + connect(overviewAction, SIGNAL(triggered()), this, SLOT(show())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(show())); @@ -202,6 +215,8 @@ void BitcoinGUI::createActions() connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(show())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); + connect(messageAction, SIGNAL(triggered()), this, SLOT(show())); + connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage())); quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setToolTip(tr("Quit application")); @@ -247,6 +262,10 @@ void BitcoinGUI::createMenuBar() // Configure the menus QMenu *file = appMenuBar->addMenu(tr("&File")); +#ifndef FIRST_CLASS_MESSAGING + file->addAction(messageAction); + file->addSeparator(); +#endif file->addAction(quitAction); QMenu *settings = appMenuBar->addMenu(tr("&Settings")); @@ -269,6 +288,9 @@ void BitcoinGUI::createToolBars() toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); toolbar->addAction(addressBookAction); +#ifdef FIRST_CLASS_MESSAGING + toolbar->addAction(messageAction); +#endif QToolBar *toolbar2 = addToolBar(tr("Actions toolbar")); toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -323,6 +345,7 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) addressBookPage->setModel(walletModel->getAddressTableModel()); receiveCoinsPage->setModel(walletModel->getAddressTableModel()); sendCoinsPage->setModel(walletModel); + messagePage->setModel(walletModel); setEncryptionStatus(walletModel->getEncryptionStatus()); connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); @@ -358,6 +381,10 @@ void BitcoinGUI::createTrayIcon() // Configuration of the tray icon (or dock icon) icon menu trayIconMenu->addAction(openBitcoinAction); trayIconMenu->addSeparator(); + trayIconMenu->addAction(messageAction); +#ifndef FIRST_CLASS_MESSAGING + trayIconMenu->addSeparator(); +#endif trayIconMenu->addAction(receiveCoinsAction); trayIconMenu->addAction(sendCoinsAction); trayIconMenu->addSeparator(); @@ -648,6 +675,26 @@ void BitcoinGUI::gotoSendCoinsPage() disconnect(exportAction, SIGNAL(triggered()), 0, 0); } +void BitcoinGUI::gotoMessagePage() +{ +#ifdef FIRST_CLASS_MESSAGING + messageAction->setChecked(true); + centralWidget->setCurrentWidget(messagePage); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); +#else + messagePage->show(); + messagePage->setFocus(); +#endif +} + +void BitcoinGUI::gotoMessagePage(QString addr) +{ + gotoMessagePage(); + messagePage->setAddress(addr); +} + void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) { // Accept only URLs @@ -670,6 +717,13 @@ void BitcoinGUI::dropEvent(QDropEvent *event) event->acceptProposedAction(); } +void BitcoinGUI::handleURL(QString strURL) +{ + gotoSendCoinsPage(); + QUrl url = QUrl(strURL); + sendCoinsPage->handleURL(&url); +} + void BitcoinGUI::setEncryptionStatus(int status) { switch(status) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index a0905e44ad..09ad89a894 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -11,6 +11,7 @@ class TransactionView; class OverviewPage; class AddressBookPage; class SendCoinsDialog; +class MessagePage; class Notificator; QT_BEGIN_NAMESPACE @@ -62,6 +63,7 @@ private: AddressBookPage *addressBookPage; AddressBookPage *receiveCoinsPage; SendCoinsDialog *sendCoinsPage; + MessagePage *messagePage; QLabel *labelEncryptionIcon; QLabel *labelConnectionsIcon; @@ -75,6 +77,7 @@ private: QAction *quitAction; QAction *sendCoinsAction; QAction *addressBookAction; + QAction *messageAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -123,6 +126,10 @@ public slots: @param[out] payFee true to pay the fee, false to not pay the fee */ void askFee(qint64 nFeeRequired, bool *payFee); + void handleURL(QString strURL); + + void gotoMessagePage(); + void gotoMessagePage(QString); private slots: /** Switch to overview (home) page */ diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui index 9b301cbbfa..b31a9ce997 100644 --- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -91,6 +91,20 @@ </widget> </item> <item> + <widget class="QPushButton" name="signMessage"> + <property name="toolTip"> + <string>Sign a message to prove you own this 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="deleteButton"> <property name="toolTip"> <string>Delete the currently selected address from the list. Only sending addresses can be deleted.</string> diff --git a/src/qt/forms/messagepage.ui b/src/qt/forms/messagepage.ui new file mode 100644 index 0000000000..8afa4b59dd --- /dev/null +++ b/src/qt/forms/messagepage.ui @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MessagePage</class> + <widget class="QWidget" name="MessagePage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>627</width> + <height>380</height> + </rect> + </property> + <property name="windowTitle"> + <string>Message</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="labelExplanation"> + <property name="text"> + <string>You can sign messages with your addresses to prove you own them. Be careful to only sign statement you agree to with full details, as phishing attacks may try to trick you into signing access to them.</string> + </property> + <property name="textFormat"> + <enum>Qt::AutoText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QValidatedLineEdit" name="signFrom"> + <property name="toolTip"> + <string>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string> + </property> + <property name="maxLength"> + <number>34</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addressBookButton"> + <property name="toolTip"> + <string>Choose adress from address book</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset> + </property> + <property name="shortcut"> + <string>Alt+A</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pasteButton"> + <property name="toolTip"> + <string>Paste address from clipboard</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset> + </property> + <property name="shortcut"> + <string>Alt+P</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPlainTextEdit" name="message"> + <property name="toolTip"> + <string>Enter the message you want to sign here</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="signature"> + <property name="font"> + <font> + <italic>true</italic> + </font> + </property> + <property name="text"> + <string>Click "Sign Message" to get signature</string> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="signMessage"> + <property name="toolTip"> + <string>Sign a message to prove you own this 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="copyToClipboard"> + <property name="toolTip"> + <string>Copy the currently selected address to the system clipboard</string> + </property> + <property name="text"> + <string>&Copy to Clipboard</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset> + </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> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QValidatedLineEdit</class> + <extends>QLineEdit</extends> + <header>qvalidatedlineedit.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="../bitcoin.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/qt/messagepage.cpp b/src/qt/messagepage.cpp new file mode 100644 index 0000000000..dee1837ed6 --- /dev/null +++ b/src/qt/messagepage.cpp @@ -0,0 +1,107 @@ +#include <string> +#include <vector> + +#include "main.h" +#include "wallet.h" +#include "init.h" +#include "util.h" + +#include "messagepage.h" +#include "ui_messagepage.h" + +#include "addressbookpage.h" +#include "guiutil.h" +#include "walletmodel.h" + +#include <QClipboard> +#include <QInputDialog> +#include <QList> +#include <QListWidgetItem> +#include <QMessageBox> + +MessagePage::MessagePage(QWidget *parent) : + QDialog(parent), + ui(new Ui::MessagePage) +{ + ui->setupUi(this); + + GUIUtil::setupAddressWidget(ui->signFrom, this); +} + +MessagePage::~MessagePage() +{ + delete ui; +} + +void MessagePage::setModel(WalletModel *model) +{ + this->model = model; +} + +void MessagePage::setAddress(QString addr) +{ + ui->signFrom->setText(addr); + ui->message->setFocus(); +} + +void MessagePage::on_pasteButton_clicked() +{ + setAddress(QApplication::clipboard()->text()); +} + +void MessagePage::on_addressBookButton_clicked() +{ + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this); + dlg.setModel(model->getAddressTableModel()); + if(dlg.exec()) + { + setAddress(dlg.getReturnValue()); + } +} + +void MessagePage::on_copyToClipboard_clicked() +{ + QApplication::clipboard()->setText(ui->signature->text()); +} + +void MessagePage::on_signMessage_clicked() +{ + QString address = ui->signFrom->text(); + + CBitcoinAddress addr(address.toStdString()); + if (!addr.IsValid()) + { + QMessageBox::critical(this, tr("Error signing"), tr("%1 is not a valid address.").arg(address), + QMessageBox::Abort, QMessageBox::Abort); + return; + } + + WalletModel::UnlockContext ctx(model->requestUnlock()); + if(!ctx.isValid()) + { + // Unlock wallet was cancelled + return; + } + + CKey key; + if (!pwalletMain->GetKey(addr, key)) + { + QMessageBox::critical(this, tr("Error signing"), tr("Private key for %1 is not available.").arg(address), + QMessageBox::Abort, QMessageBox::Abort); + return; + } + + CDataStream ss(SER_GETHASH); + ss << strMessageMagic; + ss << ui->message->document()->toPlainText().toStdString(); + + std::vector<unsigned char> vchSig; + if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) + { + QMessageBox::critical(this, tr("Error signing"), tr("Sign failed"), + QMessageBox::Abort, QMessageBox::Abort); + } + + ui->signature->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size()))); + ui->signature->setFont(GUIUtil::bitcoinAddressFont()); +} diff --git a/src/qt/messagepage.h b/src/qt/messagepage.h new file mode 100644 index 0000000000..55e6228124 --- /dev/null +++ b/src/qt/messagepage.h @@ -0,0 +1,38 @@ +#ifndef MESSAGEPAGE_H +#define MESSAGEPAGE_H + +#include <QDialog> + +namespace Ui { + class MessagePage; +} +class WalletModel; + +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE + +class MessagePage : public QDialog +{ + Q_OBJECT + +public: + explicit MessagePage(QWidget *parent = 0); + ~MessagePage(); + + void setModel(WalletModel *model); + + void setAddress(QString); + +private: + Ui::MessagePage *ui; + WalletModel *model; + +private slots: + void on_pasteButton_clicked(); + void on_addressBookButton_clicked(); + + void on_signMessage_clicked(); + void on_copyToClipboard_clicked(); +}; + +#endif // MESSAGEPAGE_H diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp new file mode 100644 index 0000000000..2ed8b915c5 --- /dev/null +++ b/src/qt/qtipcserver.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file license.txt or http://www.opensource.org/licenses/mit-license.php. + +#include <boost/algorithm/string.hpp> +#include <boost/interprocess/ipc/message_queue.hpp> +#include <boost/tokenizer.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +#include "headers.h" + +using namespace boost::interprocess; +using namespace boost::posix_time; +using namespace boost; +using namespace std; + +void ipcShutdown() +{ + message_queue::remove("BitcoinURL"); +} + +void ipcThread(void* parg) +{ + message_queue* mq = (message_queue*)parg; + char strBuf[257]; + size_t nSize; + unsigned int nPriority; + loop + { + ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100); + if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) + { + strBuf[nSize] = '\0'; + // Convert bitcoin:// URLs to bitcoin: URIs + if (strBuf[8] == '/' && strBuf[9] == '/') + { + for (int i = 8; i < 256; i++) + { + strBuf[i] = strBuf[i+2]; + } + } + ThreadSafeHandleURL(strBuf); + Sleep(1000); + } + if (fShutdown) + { + ipcShutdown(); + break; + } + } + ipcShutdown(); +} + +void ipcInit() +{ + message_queue* mq; + char strBuf[257]; + size_t nSize; + unsigned int nPriority; + try { + mq = new message_queue(open_or_create, "BitcoinURL", 2, 256); + + // Make sure we don't lose any bitcoin: URIs + for (int i = 0; i < 2; i++) + { + ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1); + if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) + { + strBuf[nSize] = '\0'; + // Convert bitcoin:// URLs to bitcoin: URIs + if (strBuf[8] == '/' && strBuf[9] == '/') + { + for (int i = 8; i < 256; i++) + { + strBuf[i] = strBuf[i+2]; + } + } + ThreadSafeHandleURL(strBuf); + } + else + break; + } + + // Make sure only one bitcoin instance is listening + message_queue::remove("BitcoinURL"); + mq = new message_queue(open_or_create, "BitcoinURL", 2, 256); + } + catch (interprocess_exception &ex) { + return; + } + if (!CreateThread(ipcThread, mq)) + { + delete mq; + } +} diff --git a/src/qt/qtipcserver.h b/src/qt/qtipcserver.h new file mode 100644 index 0000000000..1de0334afd --- /dev/null +++ b/src/qt/qtipcserver.h @@ -0,0 +1,2 @@ +void ipcInit(); +void ipcShutdown(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 762f27dfa6..0d9a604d3b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -11,6 +11,7 @@ #include <QMessageBox> #include <QLocale> #include <QTextDocument> +#include <QScrollBar> SendCoinsDialog::SendCoinsDialog(QWidget *parent) : QDialog(parent), @@ -29,6 +30,8 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) : connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry())); connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); + + fNewRecipientAllowed = true; } void SendCoinsDialog::setModel(WalletModel *model) @@ -91,6 +94,8 @@ void SendCoinsDialog::on_sendButton_clicked() formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address)); } + fNewRecipientAllowed = false; + QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"), tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))), QMessageBox::Yes|QMessageBox::Cancel, @@ -98,6 +103,7 @@ void SendCoinsDialog::on_sendButton_clicked() if(retval != QMessageBox::Yes) { + fNewRecipientAllowed = true; return; } @@ -105,6 +111,7 @@ void SendCoinsDialog::on_sendButton_clicked() if(!ctx.isValid()) { // Unlock wallet was cancelled + fNewRecipientAllowed = true; return; } @@ -151,6 +158,7 @@ void SendCoinsDialog::on_sendButton_clicked() accept(); break; } + fNewRecipientAllowed = true; } void SendCoinsDialog::clear() @@ -188,6 +196,12 @@ SendCoinsEntry *SendCoinsDialog::addEntry() // Focus the field, so that entry can start immediately entry->clear(); + entry->setFocus(); + ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint()); + QCoreApplication::instance()->processEvents(); + QScrollBar* bar = ui->scrollArea->verticalScrollBar(); + if (bar) + bar->setSliderPosition(bar->maximum()); return entry; } @@ -229,6 +243,9 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev) void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) { + if (!fNewRecipientAllowed) + return; + SendCoinsEntry *entry = 0; // Replace the first entry if it is still unused if(ui->entries->count() == 1) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 82910257f0..847ee8b697 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -43,6 +43,7 @@ public slots: private: Ui::SendCoinsDialog *ui; WalletModel *model; + bool fNewRecipientAllowed; private slots: void on_sendButton_clicked(); diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 23b11ccdde..ab5460f8c2 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -151,3 +151,8 @@ bool SendCoinsEntry::isClear() return ui->payTo->text().isEmpty(); } +void SendCoinsEntry::setFocus() +{ + ui->payTo->setFocus(); +} + diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index b7f4a0af3b..cdbf893264 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -31,6 +31,8 @@ public: */ QWidget *setupTabChain(QWidget *prev); + void setFocus(); + public slots: void setRemoveEnabled(bool enabled); void clear(); diff --git a/src/qtui.h b/src/qtui.h index 17fc44e94b..9791ba544d 100644 --- a/src/qtui.h +++ b/src/qtui.h @@ -40,6 +40,7 @@ extern int MyMessageBox(const std::string& message, const std::string& caption=" #define wxMessageBox MyMessageBox extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1); extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent); +extern void ThreadSafeHandleURL(const std::string& strURL); extern void CalledSetStatusBar(const std::string& strText, int nField); extern void UIThreadCall(boost::function0<void> fn); extern void MainFrameRepaint(); |