diff options
Diffstat (limited to 'src/qt')
35 files changed, 322 insertions, 176 deletions
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 517aa49e2b..f2ddbf259b 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -21,6 +21,41 @@ #include <QMessageBox> #include <QSortFilterProxyModel> +class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel +{ + const QString m_type; + +public: + AddressBookSortFilterProxyModel(const QString& type, QObject* parent) + : QSortFilterProxyModel(parent) + , m_type(type) + { + setDynamicSortFilter(true); + setFilterCaseSensitivity(Qt::CaseInsensitive); + setSortCaseSensitivity(Qt::CaseInsensitive); + } + +protected: + bool filterAcceptsRow(int row, const QModelIndex& parent) const + { + auto model = sourceModel(); + auto label = model->index(row, AddressTableModel::Label, parent); + + if (model->data(label, AddressTableModel::TypeRole).toString() != m_type) { + return false; + } + + auto address = model->index(row, AddressTableModel::Address, parent); + + if (filterRegExp().indexIn(model->data(address).toString()) < 0 && + filterRegExp().indexIn(model->data(label).toString()) < 0) { + return false; + } + + return true; + } +}; + AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), @@ -69,10 +104,12 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, 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->newAddress->setVisible(true); break; case ReceivingTab: 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->newAddress->setVisible(false); break; } @@ -113,24 +150,12 @@ void AddressBookPage::setModel(AddressTableModel *_model) if(!_model) return; - proxyModel = new QSortFilterProxyModel(this); + auto type = tab == ReceivingTab ? AddressTableModel::Receive : AddressTableModel::Send; + proxyModel = new AddressBookSortFilterProxyModel(type, this); proxyModel->setSourceModel(_model); - proxyModel->setDynamicSortFilter(true); - proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - switch(tab) - { - case ReceivingTab: - // Receive filter - proxyModel->setFilterRole(AddressTableModel::TypeRole); - proxyModel->setFilterFixedString(AddressTableModel::Receive); - break; - case SendingTab: - // Send filter - proxyModel->setFilterRole(AddressTableModel::TypeRole); - proxyModel->setFilterFixedString(AddressTableModel::Send); - break; - } + + connect(ui->searchLineEdit, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterWildcard(QString))); + ui->tableView->setModel(proxyModel); ui->tableView->sortByColumn(0, Qt::AscendingOrder); @@ -188,10 +213,11 @@ void AddressBookPage::on_newAddress_clicked() if(!model) return; - EditAddressDialog dlg( - tab == SendingTab ? - EditAddressDialog::NewSendingAddress : - EditAddressDialog::NewReceivingAddress, this); + if (tab == ReceivingTab) { + return; + } + + EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, this); dlg.setModel(model); if(dlg.exec()) { diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 54a43478d1..8877d07330 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -7,6 +7,7 @@ #include <QDialog> +class AddressBookSortFilterProxyModel; class AddressTableModel; class PlatformStyle; @@ -18,7 +19,6 @@ QT_BEGIN_NAMESPACE class QItemSelection; class QMenu; class QModelIndex; -class QSortFilterProxyModel; QT_END_NAMESPACE /** Widget that shows a list of sending or receiving addresses. @@ -53,7 +53,7 @@ private: Mode mode; Tabs tab; QString returnValue; - QSortFilterProxyModel *proxyModel; + AddressBookSortFilterProxyModel *proxyModel; QMenu *contextMenu; QAction *deleteAction; // to be able to explicitly disable it QString newAddressToSelect; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 4f9a79d654..801334483a 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -441,6 +441,8 @@ int AddressTableModel::lookupAddress(const QString &address) const } } +OutputType AddressTableModel::GetDefaultAddressType() const { return wallet->m_default_address_type; }; + void AddressTableModel::emitDataChanged(int idx) { Q_EMIT dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 11439e25d5..ed7a4e6f43 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -8,7 +8,7 @@ #include <QAbstractTableModel> #include <QStringList> -enum OutputType : int; +enum class OutputType; class AddressTablePriv; class WalletModel; @@ -76,6 +76,8 @@ public: EditStatus getEditStatus() const { return editStatus; } + OutputType GetDefaultAddressType() const; + private: WalletModel *walletModel; CWallet *wallet; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index ab381bfb5d..627c3e00f1 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -251,7 +251,7 @@ private: QTimer *pollShutdownTimer; #ifdef ENABLE_WALLET PaymentServer* paymentServer; - WalletModel *walletModel; + std::vector<WalletModel*> m_wallet_models; #endif int returnValue; const PlatformStyle *platformStyle; @@ -333,7 +333,7 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv): pollShutdownTimer(0), #ifdef ENABLE_WALLET paymentServer(0), - walletModel(0), + m_wallet_models(), #endif returnValue(0) { @@ -451,8 +451,10 @@ void BitcoinApplication::requestShutdown() #ifdef ENABLE_WALLET window->removeAllWallets(); - delete walletModel; - walletModel = 0; + for (WalletModel *walletModel : m_wallet_models) { + delete walletModel; + } + m_wallet_models.clear(); #endif delete clientModel; clientModel = 0; @@ -481,16 +483,20 @@ void BitcoinApplication::initializeResult(bool success) window->setClientModel(clientModel); #ifdef ENABLE_WALLET - // TODO: Expose secondary wallets - if (!vpwallets.empty()) - { - walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel); + bool fFirstWallet = true; + for (CWalletRef pwallet : vpwallets) { + WalletModel * const walletModel = new WalletModel(platformStyle, pwallet, optionsModel); - window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); - window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); + window->addWallet(walletModel); + if (fFirstWallet) { + window->setCurrentWallet(walletModel->getWalletName()); + fFirstWallet = false; + } connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)), paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray))); + + m_wallet_models.push_back(walletModel); } #endif @@ -690,7 +696,7 @@ int main(int argc, char *argv[]) // Allow parameter interaction before we create the options model app.parameterSetup(); // Load GUI settings from QSettings - app.createOptionsModel(gArgs.IsArgSet("-resetguisettings")); + app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false)); // Subscribe to global signals from core uiInterface.InitMessage.connect(InitMessage); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2f6a377a68..e4207fce99 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -21,6 +21,7 @@ #ifdef ENABLE_WALLET #include <qt/walletframe.h> #include <qt/walletmodel.h> +#include <qt/walletview.h> #endif // ENABLE_WALLET #ifdef Q_OS_MAC @@ -36,6 +37,7 @@ #include <QAction> #include <QApplication> +#include <QComboBox> #include <QDateTime> #include <QDesktopWidget> #include <QDragEnterEvent> @@ -70,10 +72,6 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM = #endif ; -/** Display name for default wallet name. Uses tilde to avoid name - * collisions in the future with additional wallets */ -const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; - BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : QMainWindow(parent), enableWallet(false), @@ -88,6 +86,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle * progressBar(0), progressDialog(0), appMenuBar(0), + appToolBar(0), overviewAction(0), historyAction(0), quitAction(0), @@ -455,6 +454,7 @@ void BitcoinGUI::createToolBars() if(walletFrame) { QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); + appToolBar = toolbar; toolbar->setContextMenuPolicy(Qt::PreventContextMenu); toolbar->setMovable(false); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -463,6 +463,15 @@ void BitcoinGUI::createToolBars() toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); overviewAction->setChecked(true); + +#ifdef ENABLE_WALLET + QWidget *spacer = new QWidget(); + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + toolbar->addWidget(spacer); + + m_wallet_selector = new QComboBox(); + connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&))); +#endif } } @@ -529,12 +538,22 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) } #ifdef ENABLE_WALLET -bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel) +bool BitcoinGUI::addWallet(WalletModel *walletModel) { if(!walletFrame) return false; + const QString name = walletModel->getWalletName(); setWalletActionsEnabled(true); - return walletFrame->addWallet(name, walletModel); + m_wallet_selector->addItem(name); + if (m_wallet_selector->count() == 2) { + m_wallet_selector_label = new QLabel(); + m_wallet_selector_label->setText(tr("Wallet:") + " "); + m_wallet_selector_label->setBuddy(m_wallet_selector); + appToolBar->addWidget(m_wallet_selector_label); + appToolBar->addWidget(m_wallet_selector); + } + rpcConsole->addWallet(walletModel); + return walletFrame->addWallet(walletModel); } bool BitcoinGUI::setCurrentWallet(const QString& name) @@ -983,12 +1002,15 @@ void BitcoinGUI::showEvent(QShowEvent *event) } #ifdef ENABLE_WALLET -void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label) +void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName) { // On new transaction, make an info balloon QString msg = tr("Date: %1\n").arg(date) + - tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) + - tr("Type: %1\n").arg(type); + tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)); + if (WalletModel::isMultiwallet() && !walletName.isEmpty()) { + msg += tr("Wallet: %1\n").arg(walletName); + } + msg += tr("Type: %1\n").arg(type); if (!label.isEmpty()) msg += tr("Label: %1\n").arg(label); else if (!address.isEmpty()) @@ -1079,6 +1101,20 @@ void BitcoinGUI::setEncryptionStatus(int status) break; } } + +void BitcoinGUI::updateWalletStatus() +{ + if (!walletFrame) { + return; + } + WalletView * const walletView = walletFrame->currentWalletView(); + if (!walletView) { + return; + } + WalletModel * const walletModel = walletView->getWalletModel(); + setEncryptionStatus(walletModel->getEncryptionStatus()); + setHDStatus(walletModel->hdEnabled()); +} #endif // ENABLE_WALLET void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index ddb7ecb76a..b9e92f2d5b 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -33,6 +33,7 @@ class ModalOverlay; QT_BEGIN_NAMESPACE class QAction; +class QComboBox; class QProgressBar; class QProgressDialog; QT_END_NAMESPACE @@ -46,7 +47,6 @@ class BitcoinGUI : public QMainWindow Q_OBJECT public: - static const QString DEFAULT_WALLET; static const std::string DEFAULT_UIPLATFORM; explicit BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0); @@ -62,8 +62,7 @@ public: 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); + bool addWallet(WalletModel *walletModel); void removeAllWallets(); #endif // ENABLE_WALLET bool enableWallet; @@ -90,6 +89,7 @@ private: QProgressDialog *progressDialog; QMenuBar *appMenuBar; + QToolBar *appToolBar; QAction *overviewAction; QAction *historyAction; QAction *quitAction; @@ -112,6 +112,9 @@ private: QAction *openAction; QAction *showHelpMessageAction; + QLabel *m_wallet_selector_label; + QComboBox *m_wallet_selector; + QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; Notificator *notificator; @@ -171,6 +174,12 @@ public Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr); #ifdef ENABLE_WALLET + bool setCurrentWallet(const QString& name); + /** Set the UI status indicators based on the currently selected wallet. + */ + void updateWalletStatus(); + +private: /** Set the encryption status as shown in the UI. @param[in] status current encryption status @see WalletModel::EncryptionStatus @@ -183,10 +192,11 @@ public Q_SLOTS: */ void setHDStatus(int hdEnabled); +public Q_SLOTS: bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ - void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName); #endif // ENABLE_WALLET private Q_SLOTS: diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index b83755ab30..a45e9f85c1 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -206,7 +206,7 @@ void CoinControlDialog::showMenu(const QPoint &point) contextMenuItem = item; // disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu - if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) + if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode) { copyTransactionHashAction->setEnabled(true); if (model->isLockedCoin(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) @@ -374,7 +374,7 @@ void CoinControlDialog::radioListMode(bool checked) // checkbox clicked by user void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) { - if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) + if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode) { COutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index a945fc6aa0..38411c499f 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -11,7 +11,6 @@ #include <QDataWidgetMapper> #include <QMessageBox> -extern OutputType g_address_type; EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), @@ -26,10 +25,6 @@ EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : switch(mode) { - case NewReceivingAddress: - setWindowTitle(tr("New receiving address")); - ui->addressEdit->setEnabled(false); - break; case NewSendingAddress: setWindowTitle(tr("New sending address")); break; @@ -74,13 +69,12 @@ bool EditAddressDialog::saveCurrentRow() switch(mode) { - case NewReceivingAddress: case NewSendingAddress: address = model->addRow( - mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive, + AddressTableModel::Send, ui->labelEdit->text(), ui->addressEdit->text(), - g_address_type); + model->GetDefaultAddressType()); break; case EditReceivingAddress: case EditSendingAddress: diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h index ddb67ece72..41c5d1708a 100644 --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -25,7 +25,6 @@ class EditAddressDialog : public QDialog public: enum Mode { - NewReceivingAddress, NewSendingAddress, EditReceivingAddress, EditSendingAddress diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui index 264edeb720..7ac216286c 100644 --- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -22,6 +22,13 @@ </widget> </item> <item> + <widget class="QLineEdit" name="searchLineEdit"> + <property name="placeholderText"> + <string>Enter address or label to search</string> + </property> + </widget> + </item> + <item> <widget class="QTableView" name="tableView"> <property name="contextMenuPolicy"> <enum>Qt::CustomContextMenu</enum> diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index bba822882e..695ed61228 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -413,6 +413,22 @@ <number>4</number> </property> <item> + <widget class="QLabel" name="WalletSelectorLabel"> + <property name="text"> + <string>Wallet: </string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="WalletSelector"> + <item> + <property name="text"> + <string>(none)</string> + </property> + </item> + </widget> + </item> + <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 7c3c68bfef..7b653a99da 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -137,15 +137,6 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); } -void setupAmountWidget(QLineEdit *widget, QWidget *parent) -{ - QDoubleValidator *amountValidator = new QDoubleValidator(parent); - amountValidator->setDecimals(8); - amountValidator->setBottom(0.0); - widget->setValidator(amountValidator); - widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); -} - bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) { // return if URI is not valid or is no bitcoin: URI @@ -209,14 +200,6 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) { - // Convert bitcoin:// to bitcoin: - // - // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host, - // which will lower-case it (and thus invalidate the address). - if(uri.startsWith("bitcoin://", Qt::CaseInsensitive)) - { - uri.replace(0, 10, "bitcoin:"); - } QUrl uriInstance(uri); return parseBitcoinURI(uriInstance, out); } diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 71a69483f5..bbbeaf2c43 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -40,9 +40,8 @@ namespace GUIUtil // Return a monospace font QFont fixedPitchFont(); - // Set up widgets for address and amounts + // Set up widget for address void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); - void setupAmountWidget(QLineEdit *widget, QWidget *parent); // Parse "bitcoin:" URI into recipient object, return true on successful parsing bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); @@ -141,7 +140,7 @@ namespace GUIUtil * Makes a QTableView last column feel as if it was being resized from its left border. * Also makes sure the column widths are never larger than the table's viewport. * In Qt, all columns are resizable from the right, but it's not intuitive resizing the last column from the right. - * Usually our second to last columns behave as if stretched, and when on strech mode, columns aren't resizable + * Usually our second to last columns behave as if stretched, and when on stretch mode, columns aren't resizable * interactively or programmatically. * * This helper object takes care of this issue. diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index b573dbe226..249418213f 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -81,7 +81,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri // keep a vector of samples of verification progress at height blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress)); - // show progress speed if we have more then one sample + // show progress speed if we have more than one sample if (blockProcessTime.size() >= 2) { double progressDelta = 0; double progressPerHour = 0; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 8ad4fa31f1..65ef250440 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -404,7 +404,12 @@ void PaymentServer::handleURIOrFile(const QString& s) return; } - if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI + if (s.startsWith("bitcoin://", Qt::CaseInsensitive)) + { + Q_EMIT message(tr("URI handling"), tr("'bitcoin://' is not a valid URI. Use 'bitcoin:' instead."), + CClientUIInterface::MSG_ERROR); + } + else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI { #if QT_VERSION < 0x050000 QUrl uri(s); @@ -634,8 +639,6 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r payment.add_transactions(transaction.data(), transaction.size()); // Create a new refund address, or re-use: - QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant); - std::string strAccount = account.toStdString(); CPubKey newKey; if (wallet->GetKeyFromPool(newKey)) { // BIP70 requests encode the scriptPubKey directly, so we are not restricted to address @@ -643,10 +646,11 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r // use for change. Despite an actual payment and not change, this is a close match: // it's the output type we use subject to privacy issues, but not restricted by what // other software supports. - const OutputType change_type = g_change_type != OUTPUT_TYPE_NONE ? g_change_type : g_address_type; + const OutputType change_type = wallet->m_default_change_type != OutputType::NONE ? wallet->m_default_change_type : wallet->m_default_address_type; wallet->LearnRelatedScripts(newKey, change_type); CTxDestination dest = GetDestinationForKey(newKey, change_type); - wallet->SetAddressBook(dest, strAccount, "refund"); + std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString(); + wallet->SetAddressBook(dest, label, "refund"); CScript s = GetScriptForDestination(dest); payments::Output* refund_to = payment.add_refund_to(); @@ -770,7 +774,7 @@ bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails { bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime()); if (fVerified) { - const QString requestExpires = QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", (int64_t)requestDetails.expires())); + const QString requestExpires = QString::fromStdString(FormatISO8601DateTime((int64_t)requestDetails.expires())); qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".") .arg(__func__) .arg(requestExpires); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 7fd5285467..c8b6366db0 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -95,13 +95,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this); // configure bech32 checkbox, disable if launched with legacy as default: - if (model->getDefaultAddressType() == OUTPUT_TYPE_BECH32) { + if (model->getDefaultAddressType() == OutputType::BECH32) { ui->useBech32->setCheckState(Qt::Checked); } else { ui->useBech32->setCheckState(Qt::Unchecked); } - ui->useBech32->setVisible(model->getDefaultAddressType() != OUTPUT_TYPE_LEGACY); + ui->useBech32->setVisible(model->getDefaultAddressType() != OutputType::LEGACY); } } @@ -145,15 +145,15 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString label = ui->reqLabel->text(); /* Generate new receiving address */ OutputType address_type = model->getDefaultAddressType(); - if (address_type != OUTPUT_TYPE_LEGACY) { - address_type = ui->useBech32->isChecked() ? OUTPUT_TYPE_BECH32 : OUTPUT_TYPE_P2SH_SEGWIT; + if (address_type != OutputType::LEGACY) { + address_type = ui->useBech32->isChecked() ? OutputType::BECH32 : OutputType::P2SH_SEGWIT; } address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type); SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text()); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setModel(model->getOptionsModel()); + dialog->setModel(model); dialog->setInfo(info); dialog->show(); clear(); @@ -166,7 +166,7 @@ void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex & { const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel(); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); - dialog->setModel(model->getOptionsModel()); + dialog->setModel(model); dialog->setInfo(submodel->entry(index.row()).recipient); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index d4cb0e5ba2..75146e2214 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -108,12 +108,12 @@ ReceiveRequestDialog::~ReceiveRequestDialog() delete ui; } -void ReceiveRequestDialog::setModel(OptionsModel *_model) +void ReceiveRequestDialog::setModel(WalletModel *_model) { this->model = _model; if (_model) - connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(update())); // update the display unit if necessary update(); @@ -143,11 +143,14 @@ void ReceiveRequestDialog::update() 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::formatHtmlWithUnit(model->getDisplayUnit(), info.amount) + "<br>"; + html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->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>"; + if(model->isMultiwallet()) { + html += "<b>"+tr("Wallet")+"</b>: " + GUIUtil::HtmlEscape(model->getWalletName()) + "<br>"; + } ui->outUri->setText(html); #ifdef USE_QRCODE diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 21bbf1edb7..23c5529535 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -12,8 +12,6 @@ #include <QLabel> #include <QPainter> -class OptionsModel; - namespace Ui { class ReceiveRequestDialog; } @@ -53,7 +51,7 @@ public: explicit ReceiveRequestDialog(QWidget *parent = 0); ~ReceiveRequestDialog(); - void setModel(OptionsModel *model); + void setModel(WalletModel *model); void setInfo(const SendCoinsRecipient &info); private Q_SLOTS: @@ -64,7 +62,7 @@ private Q_SLOTS: private: Ui::ReceiveRequestDialog *ui; - OptionsModel *model; + WalletModel *model; SendCoinsRecipient info; }; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 1aa4de03ca..c41e19f6f5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -12,6 +12,7 @@ #include <qt/bantablemodel.h> #include <qt/clientmodel.h> #include <qt/platformstyle.h> +#include <qt/walletmodel.h> #include <chainparams.h> #include <netbase.h> #include <rpc/server.h> @@ -84,7 +85,7 @@ class RPCExecutor : public QObject Q_OBJECT public Q_SLOTS: - void request(const QString &command); + void request(const QString &command, const QString &walletID); Q_SIGNALS: void reply(int category, const QString &command); @@ -145,7 +146,7 @@ public: * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data */ -bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut) +bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID) { std::vector< std::vector<std::string> > stack; stack.push_back(std::vector<std::string>()); @@ -303,10 +304,8 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end())); req.strMethod = stack.back()[0]; #ifdef ENABLE_WALLET - // TODO: Move this logic to WalletModel - if (!vpwallets.empty()) { - // in Qt, use always the wallet with index 0 when running with multiple wallets - QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName())); + if (walletID && !walletID->empty()) { + QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID)); req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length()); } #endif @@ -385,7 +384,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & } } -void RPCExecutor::request(const QString &command) +void RPCExecutor::request(const QString &command, const QString &walletID) { try { @@ -416,7 +415,8 @@ void RPCExecutor::request(const QString &command) " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); return; } - if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand)) + std::string wallet_id = walletID.toStdString(); + if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand, nullptr, &wallet_id)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; @@ -478,6 +478,10 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller())); connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); + // disable the wallet selector by default + ui->WalletSelector->setVisible(false); + ui->WalletSelectorLabel->setVisible(false); + // set library version labels #ifdef ENABLE_WALLET ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); @@ -687,6 +691,23 @@ void RPCConsole::setClientModel(ClientModel *model) } } +#ifdef ENABLE_WALLET +void RPCConsole::addWallet(WalletModel * const walletModel) +{ + const QString name = walletModel->getWalletName(); + // use name for text and internal data object (to allow to move to a wallet id later) + ui->WalletSelector->addItem(name, name); + if (ui->WalletSelector->count() == 2 && !isVisible()) { + // First wallet added, set to default so long as the window isn't presently visible (and potentially in use) + ui->WalletSelector->setCurrentIndex(1); + } + if (ui->WalletSelector->count() > 2) { + ui->WalletSelector->setVisible(true); + ui->WalletSelectorLabel->setVisible(true); + } +} +#endif + static QString categoryClass(int category) { switch(category) @@ -874,8 +895,25 @@ void RPCConsole::on_lineEdit_returnPressed() cmdBeforeBrowsing = QString(); + QString walletID; +#ifdef ENABLE_WALLET + const int wallet_index = ui->WalletSelector->currentIndex(); + if (wallet_index > 0) { + walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>(); + } + + if (m_last_wallet_id != walletID) { + if (walletID.isEmpty()) { + message(CMD_REQUEST, tr("Executing command without any wallet")); + } else { + message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID)); + } + m_last_wallet_id = walletID; + } +#endif + message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); - Q_EMIT cmdRequest(cmd); + Q_EMIT cmdRequest(cmd, walletID); cmd = QString::fromStdString(strFilteredCmd); @@ -923,7 +961,7 @@ void RPCConsole::startExecutor() // Replies from executor object must go to this object connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString))); // Requests from this object must go to executor - connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString))); + connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString))); // On stopExecutor signal // - quit the Qt event loop in the execution thread diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index c41cbb0933..c97260b2c3 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -17,6 +17,7 @@ class ClientModel; class PlatformStyle; class RPCTimerInterface; +class WalletModel; namespace Ui { class RPCConsole; @@ -36,12 +37,13 @@ public: explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); - static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr); - static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr) { - return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut); + static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr); + static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) { + return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut, walletID); } void setClientModel(ClientModel *model); + void addWallet(WalletModel * const walletModel); enum MessageClass { MC_ERROR, @@ -120,7 +122,7 @@ public Q_SLOTS: Q_SIGNALS: // For RPC command executor void stopExecutor(); - void cmdRequest(const QString &command); + void cmdRequest(const QString &command, const QString &walletID); private: void startExecutor(); @@ -151,6 +153,7 @@ private: int consoleFontSize; QCompleter *autoCompleter; QThread thread; + QString m_last_wallet_id; /** Update UI with latest network info from model. */ void updateNetworkState(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index ec7edd48cd..8a52aadbb0 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -277,8 +277,11 @@ void SendCoinsDialog::on_sendButton_clicked() QStringList formatted; for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) { - // generate bold amount string + // generate bold amount string with wallet name in case of multiwallet QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); + if (model->isMultiwallet()) { + amount.append(" <u>"+tr("from wallet %1").arg(GUIUtil::HtmlEscape(model->getWalletName()))+"</u> "); + } amount.append("</b>"); // generate monospace address string QString address = "<span style='font-family: monospace;'>" + rcp.address; diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 5df1282f73..66e9dd0465 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -91,7 +91,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) pixPaint.setFont(QFont(font, 15*fontFactor)); - // if the version string is to long, reduce size + // if the version string is too long, reduce size fm = pixPaint.fontMetrics(); int versionTextWidth = fm.width(versionText); if(versionTextWidth > titleTextWidth+paddingRight-10) { diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 8415250630..59938f704a 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -51,7 +51,7 @@ void URITests::uriTests() QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); - QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv)); + QVERIFY(GUIUtil::parseBitcoinURI("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 976aadc0af..c9898e52ca 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -150,9 +150,6 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st // src/qt/test/test_bitcoin-qt -platform cocoa # macOS void TestGUI() { - g_address_type = OUTPUT_TYPE_P2SH_SEGWIT; - g_change_type = OUTPUT_TYPE_P2SH_SEGWIT; - // Set up wallet and chain with 105 blocks (5 mature blocks for spending). TestChain100Setup test; for (int i = 0; i < 5; ++i) { @@ -163,7 +160,7 @@ void TestGUI() wallet.LoadWallet(firstRun); { LOCK(wallet.cs_wallet); - wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), g_address_type), "", "receive"); + wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet.m_default_address_type), "", "receive"); wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); } { diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index a702461f7a..6301af7553 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -31,31 +31,35 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & { QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - int type = index.data(TransactionTableModel::TypeRole).toInt(); - QDateTime datetime = index.data(TransactionTableModel::DateRole).toDateTime(); - bool involvesWatchAddress = index.data(TransactionTableModel::WatchonlyRole).toBool(); - QString address = index.data(TransactionTableModel::AddressRole).toString(); - QString label = index.data(TransactionTableModel::LabelRole).toString(); - QString txid = index.data(TransactionTableModel::TxHashRole).toString(); - qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); int status = index.data(TransactionTableModel::StatusRole).toInt(); - - if(!showInactive && status == TransactionStatus::Conflicted) + if (!showInactive && status == TransactionStatus::Conflicted) return false; - if(!(TYPE(type) & typeFilter)) + + int type = index.data(TransactionTableModel::TypeRole).toInt(); + if (!(TYPE(type) & typeFilter)) return false; + + bool involvesWatchAddress = index.data(TransactionTableModel::WatchonlyRole).toBool(); if (involvesWatchAddress && watchOnlyFilter == WatchOnlyFilter_No) return false; if (!involvesWatchAddress && watchOnlyFilter == WatchOnlyFilter_Yes) return false; - if(datetime < dateFrom || datetime > dateTo) + + QDateTime datetime = index.data(TransactionTableModel::DateRole).toDateTime(); + if (datetime < dateFrom || datetime > dateTo) return false; + + QString address = index.data(TransactionTableModel::AddressRole).toString(); + QString label = index.data(TransactionTableModel::LabelRole).toString(); + QString txid = index.data(TransactionTableModel::TxHashRole).toString(); if (!address.contains(m_search_string, Qt::CaseInsensitive) && ! label.contains(m_search_string, Qt::CaseInsensitive) && ! txid.contains(m_search_string, Qt::CaseInsensitive)) { return false; } - if(amount < minAmount) + + qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); + if (amount < minAmount) return false; return true; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 19cdb0fdea..cc30cf747d 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -167,10 +167,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) // Determine transaction status // Find the block the tx is in - CBlockIndex* pindex = nullptr; - BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock); - if (mi != mapBlockIndex.end()) - pindex = (*mi).second; + const CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock); // Sort order, unrecorded transactions sort to the top status.sortKey = strprintf("%010d-%01d-%010u-%03d", diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index c0b9d04269..5b13353d7b 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <qt/walletframe.h> +#include <qt/walletmodel.h> #include <qt/bitcoingui.h> #include <qt/walletview.h> @@ -39,10 +40,16 @@ void WalletFrame::setClientModel(ClientModel *_clientModel) this->clientModel = _clientModel; } -bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) +bool WalletFrame::addWallet(WalletModel *walletModel) { - if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0) + if (!gui || !clientModel || !walletModel) { return false; + } + + const QString name = walletModel->getWalletName(); + if (mapWalletViews.count(name) > 0) { + return false; + } WalletView *walletView = new WalletView(platformStyle, this); walletView->setBitcoinGUI(gui); diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 42ce69fea1..6eedcf370c 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -36,7 +36,7 @@ public: void setClientModel(ClientModel *clientModel); - bool addWallet(const QString& name, WalletModel *walletModel); + bool addWallet(WalletModel *walletModel); bool setCurrentWallet(const QString& name); bool removeWallet(const QString &name); void removeAllWallets(); @@ -59,6 +59,7 @@ private: const PlatformStyle *platformStyle; +public: WalletView *currentWalletView(); public Q_SLOTS: diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e7d9d276d7..795302be58 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -110,8 +110,9 @@ void WalletModel::updateStatus() { EncryptionStatus newEncryptionStatus = getEncryptionStatus(); - if(cachedEncryptionStatus != newEncryptionStatus) - Q_EMIT encryptionStatusChanged(newEncryptionStatus); + if(cachedEncryptionStatus != newEncryptionStatus) { + Q_EMIT encryptionStatusChanged(); + } } void WalletModel::pollBalanceChanged() @@ -275,9 +276,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact int nChangePosRet = -1; std::string strFailReason; - CWalletTx *newTx = transaction.getTransaction(); + CTransactionRef& newTx = transaction.getTransaction(); CReserveKey *keyChange = transaction.getPossibleKeyChange(); - bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl); + bool fCreated = wallet->CreateTransaction(vecSend, newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl); transaction.setTransactionFee(nFeeRequired); if (fSubtractFeeFromAmount && fCreated) transaction.reassignAmounts(nChangePosRet); @@ -309,8 +310,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran { LOCK2(cs_main, wallet->cs_wallet); - CWalletTx *newTx = transaction.getTransaction(); + std::vector<std::pair<std::string, std::string>> vOrderForm; for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { if (rcp.paymentRequest.IsInitialized()) @@ -321,22 +322,22 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } // Store PaymentRequests in wtx.vOrderForm in wallet. - std::string key("PaymentRequest"); std::string value; rcp.paymentRequest.SerializeToString(&value); - newTx->vOrderForm.push_back(make_pair(key, value)); + vOrderForm.emplace_back("PaymentRequest", std::move(value)); } else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example) - newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString())); + vOrderForm.emplace_back("Message", rcp.message.toStdString()); } + CTransactionRef& newTx = transaction.getTransaction(); CReserveKey *keyChange = transaction.getPossibleKeyChange(); CValidationState state; - if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state)) + if (!wallet->CommitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, *keyChange, g_connman.get(), state)) return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(state.GetRejectReason())); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); - ssTx << *newTx->tx; + ssTx << newTx; transaction_array.append(&(ssTx[0]), ssTx.size()); } @@ -698,7 +699,7 @@ bool WalletModel::bumpFee(uint256 hash) confirmationDialog.exec(); QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result()); - // cancel sign&broadcast if users doesn't want to bump the fee + // cancel sign&broadcast if user doesn't want to bump the fee if (retval != QMessageBox::Yes) { return false; } @@ -736,10 +737,21 @@ bool WalletModel::hdEnabled() const OutputType WalletModel::getDefaultAddressType() const { - return g_address_type; + return wallet->m_default_address_type; } int WalletModel::getDefaultConfirmTarget() const { return nTxConfirmTarget; } + +QString WalletModel::getWalletName() const +{ + LOCK(wallet->cs_wallet); + return QString::fromStdString(wallet->GetName()); +} + +bool WalletModel::isMultiwallet() +{ + return gArgs.GetArgs("-wallet").size() > 1; +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 811996b98f..ff4b38a804 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -20,7 +20,7 @@ #include <QObject> -enum OutputType : int; +enum class OutputType; class AddressTableModel; class OptionsModel; @@ -136,6 +136,8 @@ public: TransactionTableModel *getTransactionTableModel(); RecentRequestsTableModel *getRecentRequestsTableModel(); + CWallet *getWallet() const { return wallet; }; + CAmount getBalance(const CCoinControl *coinControl = nullptr) const; CAmount getUnconfirmedBalance() const; CAmount getImmatureBalance() const; @@ -225,6 +227,9 @@ public: int getDefaultConfirmTarget() const; + QString getWalletName() const; + + static bool isMultiwallet(); private: CWallet *wallet; bool fHaveWatchOnly; @@ -260,7 +265,7 @@ Q_SIGNALS: const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); // Encryption status of wallet changed - void encryptionStatusChanged(int status); + void encryptionStatusChanged(); // Signal emitted when wallet needs to be unlocked // It is valid behaviour for listeners to keep the wallet locked after this signal; diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 4b2bef2690..4df8a5687e 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -12,12 +12,6 @@ WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> & walletTransaction(0), fee(0) { - walletTransaction = new CWalletTx(); -} - -WalletModelTransaction::~WalletModelTransaction() -{ - delete walletTransaction; } QList<SendCoinsRecipient> WalletModelTransaction::getRecipients() const @@ -25,14 +19,14 @@ QList<SendCoinsRecipient> WalletModelTransaction::getRecipients() const return recipients; } -CWalletTx *WalletModelTransaction::getTransaction() const +CTransactionRef& WalletModelTransaction::getTransaction() { return walletTransaction; } unsigned int WalletModelTransaction::getTransactionSize() { - return (!walletTransaction ? 0 : ::GetVirtualTransactionSize(*walletTransaction->tx)); + return (!walletTransaction ? 0 : ::GetVirtualTransactionSize(*walletTransaction)); } CAmount WalletModelTransaction::getTransactionFee() const @@ -62,7 +56,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet) if (out.amount() <= 0) continue; if (i == nChangePosRet) i++; - subtotal += walletTransaction->tx->vout[i].nValue; + subtotal += walletTransaction->vout[i].nValue; i++; } rcp.amount = subtotal; @@ -71,7 +65,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet) { if (i == nChangePosRet) i++; - rcp.amount = walletTransaction->tx->vout[i].nValue; + rcp.amount = walletTransaction->vout[i].nValue; i++; } } diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index cd531dba4b..931e960d18 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -20,11 +20,10 @@ class WalletModelTransaction { public: explicit WalletModelTransaction(const QList<SendCoinsRecipient> &recipients); - ~WalletModelTransaction(); QList<SendCoinsRecipient> getRecipients() const; - CWalletTx *getTransaction() const; + CTransactionRef& getTransaction(); unsigned int getTransactionSize(); void setTransactionFee(const CAmount& newFee); @@ -39,7 +38,7 @@ public: private: QList<SendCoinsRecipient> recipients; - CWalletTx *walletTransaction; + CTransactionRef walletTransaction; std::unique_ptr<CReserveKey> keyChange; CAmount fee; }; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 64497a3431..cc4300a7a1 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -101,13 +101,13 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) 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))); + connect(this, SIGNAL(encryptionStatusChanged()), gui, SLOT(updateWalletStatus())); // Pass through transaction notifications - connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString))); + connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString))); // Connect HD enabled state signal - connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int))); + connect(this, SIGNAL(hdEnabledStatusChanged()), gui, SLOT(updateWalletStatus())); } } @@ -137,11 +137,11 @@ void WalletView::setWalletModel(WalletModel *_walletModel) connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); // Handle changes in encryption status - connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); + connect(_walletModel, SIGNAL(encryptionStatusChanged()), this, SIGNAL(encryptionStatusChanged())); updateEncryptionStatus(); // update HD status - Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled()); + Q_EMIT hdEnabledStatusChanged(); // Balloon pop-up for new transaction connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), @@ -172,7 +172,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int QString address = ttm->data(index, TransactionTableModel::AddressRole).toString(); QString label = ttm->data(index, TransactionTableModel::LabelRole).toString(); - Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); + Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, walletModel->getWalletName()); } void WalletView::gotoOverviewPage() @@ -234,7 +234,7 @@ void WalletView::showOutOfSyncWarning(bool fShow) void WalletView::updateEncryptionStatus() { - Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus()); + Q_EMIT encryptionStatusChanged(); } void WalletView::encryptWallet(bool status) diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 30d68e4eff..878a5966d6 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -44,6 +44,7 @@ public: The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. */ void setClientModel(ClientModel *clientModel); + WalletModel *getWalletModel() { return walletModel; } /** Set the wallet model. The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending functionality. @@ -119,11 +120,11 @@ Q_SIGNALS: /** 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); + void encryptionStatusChanged(); /** HD-Enabled status of wallet changed (only possible during startup) */ - void hdEnabledStatusChanged(int hdEnabled); + void hdEnabledStatusChanged(); /** Notify that a new transaction appeared */ - void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName); /** Notify that the out of sync warning icon has been pressed */ void outOfSyncWarningClicked(); }; |