diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 5496314a35..1237da65f7 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -64,6 +64,7 @@ QT_MOC_CPP = \ qt/moc_optionsdialog.cpp \ qt/moc_optionsmodel.cpp \ qt/moc_overviewpage.cpp \ + qt/moc_pairingpage.cpp \ qt/moc_peertablemodel.cpp \ qt/moc_peertablesortproxy.cpp \ qt/moc_paymentserver.cpp \ @@ -140,6 +141,7 @@ BITCOIN_QT_H = \ qt/optionsdialog.h \ qt/optionsmodel.h \ qt/overviewpage.h \ + qt/pairingpage.h \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/peertablesortproxy.h \ @@ -243,9 +245,11 @@ BITCOIN_QT_BASE_CPP = \ qt/notificator.cpp \ qt/optionsdialog.cpp \ qt/optionsmodel.cpp \ + qt/pairingpage.cpp \ qt/peertablemodel.cpp \ qt/peertablesortproxy.cpp \ qt/platformstyle.cpp \ + qt/qrimagewidget.cpp \ qt/qvalidatedlineedit.cpp \ qt/qvaluecombobox.cpp \ qt/rpcconsole.cpp \ @@ -267,7 +271,6 @@ BITCOIN_QT_WALLET_CPP = \ qt/overviewpage.cpp \ qt/paymentserver.cpp \ qt/psbtoperationsdialog.cpp \ - qt/qrimagewidget.cpp \ qt/receivecoinsdialog.cpp \ qt/receiverequestdialog.cpp \ qt/recentrequeststablemodel.cpp \ diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 6718b2b77c..3f0f85604a 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -252,6 +252,10 @@ public: using NotifyNetworkActiveChangedFn = std::function; virtual std::unique_ptr handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) = 0; + //! Register handler for network local changed messages. + using NotifyNetworkLocalChangedFn = std::function; + virtual std::unique_ptr handleNotifyNetworkLocalChanged(NotifyNetworkLocalChangedFn fn) = 0; + //! Register handler for notify alert messages. using NotifyAlertChangedFn = std::function; virtual std::unique_ptr handleNotifyAlertChanged(NotifyAlertChangedFn fn) = 0; diff --git a/src/net.cpp b/src/net.cpp index bb582ff503..f528374650 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -278,9 +278,11 @@ bool AddLocal(const CService& addr_, int nScore) LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore); + bool fAlready; { LOCK(g_maplocalhost_mutex); const auto [it, is_newly_added] = mapLocalHost.emplace(addr, LocalServiceInfo()); + fAlready = !is_newly_added; LocalServiceInfo &info = it->second; if (is_newly_added || nScore >= info.nScore) { info.nScore = nScore + (is_newly_added ? 0 : 1); @@ -288,6 +290,10 @@ bool AddLocal(const CService& addr_, int nScore) } } + if (!fAlready) { + uiInterface.NotifyNetworkLocalChanged(); + } + return true; } @@ -298,9 +304,12 @@ bool AddLocal(const CNetAddr &addr, int nScore) void RemoveLocal(const CService& addr) { - LOCK(g_maplocalhost_mutex); - LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort()); - mapLocalHost.erase(addr); + { + LOCK(g_maplocalhost_mutex); + LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort()); + mapLocalHost.erase(addr); + } + uiInterface.NotifyNetworkLocalChanged(); } /** vote for a local address */ diff --git a/src/node/interface_ui.cpp b/src/node/interface_ui.cpp index 4f4d240d1b..1e07419dc5 100644 --- a/src/node/interface_ui.cpp +++ b/src/node/interface_ui.cpp @@ -21,6 +21,7 @@ struct UISignals { boost::signals2::signal InitWallet; boost::signals2::signal NotifyNumConnectionsChanged; boost::signals2::signal NotifyNetworkActiveChanged; + boost::signals2::signal NotifyNetworkLocalChanged; boost::signals2::signal NotifyAlertChanged; boost::signals2::signal ShowProgress; boost::signals2::signal NotifyBlockTip; @@ -41,6 +42,7 @@ ADD_SIGNALS_IMPL_WRAPPER(InitMessage); ADD_SIGNALS_IMPL_WRAPPER(InitWallet); ADD_SIGNALS_IMPL_WRAPPER(NotifyNumConnectionsChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkActiveChanged); +ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkLocalChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyAlertChanged); ADD_SIGNALS_IMPL_WRAPPER(ShowProgress); ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip); @@ -53,6 +55,7 @@ void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_s void CClientUIInterface::InitWallet() { return g_ui_signals.InitWallet(); } void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); } void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); } +void CClientUIInterface::NotifyNetworkLocalChanged() { return g_ui_signals.NotifyNetworkLocalChanged(); } void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); } void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); } void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); } diff --git a/src/node/interface_ui.h b/src/node/interface_ui.h index 85c34f5834..4b781d3b94 100644 --- a/src/node/interface_ui.h +++ b/src/node/interface_ui.h @@ -91,6 +91,9 @@ public: /** Network activity state changed. */ ADD_SIGNALS_DECL_WRAPPER(NotifyNetworkActiveChanged, void, bool networkActive); + /** Network local addresses changed. */ + ADD_SIGNALS_DECL_WRAPPER(NotifyNetworkLocalChanged, void, ); + /** * Status bar alerts changed. */ diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 14b4cbb35e..ea15e919f3 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -392,6 +392,10 @@ public: { return MakeSignalHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn)); } + std::unique_ptr handleNotifyNetworkLocalChanged(NotifyNetworkLocalChangedFn fn) override + { + return MakeSignalHandler(::uiInterface.NotifyNetworkLocalChanged_connect(fn)); + } std::unique_ptr handleNotifyAlertChanged(NotifyAlertChangedFn fn) override { return MakeSignalHandler(::uiInterface.NotifyAlertChanged_connect(fn)); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index a36aa84551..0bbbb7b10a 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -125,6 +125,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty /* When compiled without wallet or -disablewallet is provided, * the central widget is the rpc console. */ + rpcConsole->addPairingTab(); setCentralWidget(rpcConsole); Q_EMIT consoleShown(rpcConsole); } @@ -280,6 +281,13 @@ void BitcoinGUI::createActions() historyAction->setShortcut(QKeySequence(QStringLiteral("Alt+4"))); tabGroup->addAction(historyAction); + m_action_pairing = new QAction(platformStyle->SingleColorIcon(":/icons/connect_1"), tr("&Pairing"), this); + m_action_pairing->setStatusTip(tr("Pair other software or devices with your node")); + m_action_pairing->setToolTip(m_action_pairing->statusTip()); + m_action_pairing->setCheckable(true); + m_action_pairing->setShortcut(QKeySequence(QStringLiteral("Alt+5"))); + tabGroup->addAction(m_action_pairing); + #ifdef ENABLE_WALLET // These showNormalIfMinimized are needed because Send Coins and Receive Coins // can be triggered from the tray menu, and need to show the GUI to be useful. @@ -291,6 +299,8 @@ void BitcoinGUI::createActions() connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage); connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage); + connect(m_action_pairing, &QAction::triggered, this, [this]{ showNormalIfMinimized(); }); + connect(m_action_pairing, &QAction::triggered, this, &BitcoinGUI::gotoPairingPage); #endif // ENABLE_WALLET quitAction = new QAction(tr("E&xit"), this); @@ -615,6 +625,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); + toolbar->addAction(m_action_pairing); overviewAction->setChecked(true); #ifdef ENABLE_WALLET @@ -839,7 +850,6 @@ void BitcoinGUI::removeAllWallets() void BitcoinGUI::setWalletActionsEnabled(bool enabled) { - overviewAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); historyAction->setEnabled(enabled && !isPrivacyModeActivated()); @@ -1022,6 +1032,12 @@ void BitcoinGUI::gotoOverviewPage() if (walletFrame) walletFrame->gotoOverviewPage(); } +void BitcoinGUI::gotoPairingPage() +{ + m_action_pairing->setChecked(true); + if (walletFrame) walletFrame->gotoPairingPage(); +} + void BitcoinGUI::gotoHistoryPage() { historyAction->setChecked(true); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 351256b41d..86414fbeaa 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -135,6 +135,7 @@ private: QMenuBar* appMenuBar = nullptr; QToolBar* appToolBar = nullptr; QAction* overviewAction = nullptr; + QAction* m_action_pairing = nullptr; QAction* historyAction = nullptr; QAction* quitAction = nullptr; QAction* sendCoinsAction = nullptr; @@ -283,6 +284,8 @@ public Q_SLOTS: #ifdef ENABLE_WALLET /** Switch to overview (home) page */ void gotoOverviewPage(); + /** Switch to pairing page */ + void gotoPairingPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); /** Switch to receive coins page */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e5edcd4911..2ed2fe2c95 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -265,6 +265,10 @@ void ClientModel::subscribeToCoreSignals() [this](bool network_active) { Q_EMIT networkActiveChanged(network_active); })); + m_event_handlers.emplace_back(m_node.handleNotifyNetworkLocalChanged( + [this]() { + Q_EMIT networkLocalChanged(); + })); m_event_handlers.emplace_back(m_node.handleNotifyAlertChanged( [this]() { qDebug() << "ClientModel: NotifyAlertChanged"; @@ -304,6 +308,17 @@ bool ClientModel::getProxyInfo(std::string& ip_port) const return false; } +bool ClientModel::getTorInfo(QString& out_onion) const +{ + for (const auto& [addr, info] : m_node.getNetLocalAddresses()) { + if (addr.IsTor()) { + out_onion = QString::fromStdString(addr.ToStringAddr()); + return true; + } + } + return false; +} + mempoolSamples_t ClientModel::getMempoolStatsInRange(QDateTime &from, QDateTime &to) { // get stats from the core stats model diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 9c7d46bd0b..9c26718439 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -92,6 +92,7 @@ public: QString blocksDir() const; bool getProxyInfo(std::string& ip_port) const; + bool getTorInfo(QString& out_onion) const; // caches for the best header: hash, number of blocks and block time mutable std::atomic cachedBestHeaderHeight; @@ -124,6 +125,7 @@ Q_SIGNALS: void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state); void mempoolSizeChanged(long count, size_t mempoolSizeInBytes, size_t mempoolMaxSizeInBytes); void networkActiveChanged(bool networkActive); + void networkLocalChanged(); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/pairingpage.cpp b/src/qt/pairingpage.cpp new file mode 100644 index 0000000000..593a49bf2c --- /dev/null +++ b/src/qt/pairingpage.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +PairingPage::PairingPage(QWidget *parent) : + QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + QLabel *label_experimental = new QLabel(this); + label_experimental->setStyleSheet("QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; }"); + label_experimental->setMargin(3); + label_experimental->setTextInteractionFlags(Qt::TextSelectableByMouse); + label_experimental->setWordWrap(true); + label_experimental->setText(tr("Pairing is an experimental feature that currently only works when Tor is enabled. It is expected that the pairing address below will change with future updates, and you may need to re-pair after upgrading.")); + layout->addWidget(label_experimental); + + QLabel *label_summary = new QLabel(this); + label_summary->setText(tr("Below you will find information to pair other software or devices with this node:")); + layout->addWidget(label_summary); + + QFormLayout *form_layout = new QFormLayout(); + m_onion_address = new QLineEdit(this); + m_onion_address->setReadOnly(true); + form_layout->addRow(tr("Onion address: "), m_onion_address); + + layout->addLayout(form_layout); + + m_qrcode = new QRImageWidget(this); +#ifdef USE_QRCODE + layout->addWidget(m_qrcode); +#endif + + layout->addStretch(); + + refresh(); +} + +void PairingPage::setClientModel(ClientModel *client_model) +{ + if (m_client_model) { + disconnect(m_client_model, &ClientModel::networkLocalChanged, this, &PairingPage::refresh); + } + m_client_model = client_model; + if (client_model) { + connect(client_model, &ClientModel::networkLocalChanged, this, &PairingPage::refresh); + } + refresh(); +} + +void PairingPage::refresh() +{ + QString onion; + if (m_client_model && m_client_model->getTorInfo(onion)) { + m_onion_address->setText(onion); + m_onion_address->setEnabled(true); + QString uri = QString("bitcoin-p2p://") + onion; + m_qrcode->setQR(uri); + m_qrcode->setVisible(true); + } else { + m_onion_address->setText(tr("(not connected)")); + m_onion_address->setEnabled(false); + m_qrcode->setVisible(false); + } +} diff --git a/src/qt/pairingpage.h b/src/qt/pairingpage.h new file mode 100644 index 0000000000..59c35abc65 --- /dev/null +++ b/src/qt/pairingpage.h @@ -0,0 +1,35 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_PAIRINGPAGE_H +#define BITCOIN_QT_PAIRINGPAGE_H + +#include + +class ClientModel; +class QRImageWidget; + +QT_BEGIN_NAMESPACE +class QLineEdit; +QT_END_NAMESPACE + +class PairingPage : public QWidget +{ + Q_OBJECT + +public: + explicit PairingPage(QWidget *parent = nullptr); + + void setClientModel(ClientModel *); + +public Q_SLOTS: + void refresh(); + +private: + ClientModel *m_client_model{nullptr}; + QLineEdit *m_onion_address{nullptr}; + QRImageWidget *m_qrcode{nullptr}; +}; + +#endif // BITCOIN_QT_PAIRINGPAGE_H diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index e730ed95a5..8bab93392d 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -475,6 +476,12 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty platformStyle(_platformStyle) { ui->setupUi(this); + + // Default tabs are identified by their UI index + for (int i = ui->tabWidget->count(); i--; ) { + m_tabs[TabTypes(i)] = ui->tabWidget->widget(i); + } + QSettings settings; #ifdef ENABLE_WALLET if (WalletModel::isWalletEnabled()) { @@ -673,6 +680,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ } ui->trafficGraph->setClientModel(model); + if (m_tab_pairing) m_tab_pairing->setClientModel(model); if (model && clientModel->getPeerTableModel() && clientModel->getBanTableModel()) { // Keep up to date with client setNumConnections(model->getNumConnections()); @@ -810,6 +818,15 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ } } +void RPCConsole::addPairingTab() +{ + assert(!m_tab_pairing); + m_tab_pairing = new PairingPage(this); + ui->tabWidget->insertTab(1, m_tab_pairing, tr("&Pairing")); + m_tabs[TabTypes::PAIRING] = m_tab_pairing; + if (clientModel) m_tab_pairing->setClientModel(clientModel); +} + #ifdef ENABLE_WALLET void RPCConsole::addWallet(WalletModel * const walletModel) { @@ -1412,14 +1429,34 @@ void RPCConsole::showOrHideBanTableIfRequired() ui->banHeading->setVisible(visible); } +std::vector RPCConsole::tabs() const +{ + std::vector ret; + ret.reserve(m_tabs.size()); + + std::map tabtype_map; + for (const auto& tab : m_tabs) { + tabtype_map[tab.second] = tab.first; + } + + for (int i = 0; i < ui->tabWidget->count(); ++i) { + auto tabtype = tabtype_map.find(ui->tabWidget->widget(i)); + if (tabtype != tabtype_map.end()) { + ret.push_back(tabtype->second); + } + } + return ret; +} + void RPCConsole::setTabFocus(enum TabTypes tabType) { - ui->tabWidget->setCurrentIndex(int(tabType)); + ui->tabWidget->setCurrentWidget(m_tabs[tabType]); } QString RPCConsole::tabTitle(TabTypes tab_type) const { - return ui->tabWidget->tabText(int(tab_type)); + const int tab_index = ui->tabWidget->indexOf(m_tabs.at(tab_type)); + return ui->tabWidget->tabText(tab_index); } QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const @@ -1428,6 +1465,7 @@ QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const case TabTypes::INFO: return QKeySequence(tr("Ctrl+I")); case TabTypes::CONSOLE: return QKeySequence(tr("Ctrl+T")); case TabTypes::GRAPH: return QKeySequence(tr("Ctrl+N")); + case TabTypes::PAIRING: return QKeySequence(QStringLiteral("Alt+5")); // Only used in disablewallet mode - matches wallet GUI's pairing shortcut case TabTypes::PEERS: return QKeySequence(tr("Ctrl+P")); } // no default case, so the compiler can warn about missing cases diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 285d48e0af..1785b80df6 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -19,6 +19,7 @@ #include class GuiNetWatch; +class PairingPage; class PlatformStyle; class RPCExecutor; class RPCTimerInterface; @@ -53,6 +54,7 @@ public: } void setClientModel(ClientModel *model = nullptr, int bestblock_height = 0, int64_t bestblock_date = 0, double verification_progress = 0.0); + void addPairingTab(); #ifdef ENABLE_WALLET void addWallet(WalletModel* const walletModel); @@ -71,10 +73,11 @@ public: INFO, CONSOLE, GRAPH, - PEERS + PEERS, + PAIRING, }; - std::vector tabs() const { return {TabTypes::INFO, TabTypes::CONSOLE, TabTypes::GRAPH, TabTypes::PEERS}; } + std::vector tabs() const; QString tabTitle(TabTypes tab_type) const; QKeySequence tabShortcut(TabTypes tab_type) const; @@ -165,6 +168,8 @@ private: interfaces::Node& m_node; Ui::RPCConsole* const ui; ClientModel *clientModel = nullptr; + std::map m_tabs; + PairingPage *m_tab_pairing{nullptr}; GuiNetWatch *netwatch = nullptr; QStringList history; int historyPtr = 0; diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 0e452d5e7a..406c6e2fd8 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include @@ -35,8 +36,10 @@ WalletFrame::WalletFrame(const PlatformStyle* _platformStyle, QWidget* parent) QHBoxLayout *walletFrameLayout = new QHBoxLayout(this); setContentsMargins(0,0,0,0); walletStack = new QStackedWidget(this); + m_global_stack = new QStackedWidget(this); + m_global_stack->addWidget(walletStack); walletFrameLayout->setContentsMargins(0,0,0,0); - walletFrameLayout->addWidget(walletStack); + walletFrameLayout->addWidget(m_global_stack); // hbox for no wallet QGroupBox* no_wallet_group = new QGroupBox(walletStack); @@ -53,6 +56,9 @@ WalletFrame::WalletFrame(const PlatformStyle* _platformStyle, QWidget* parent) no_wallet_group->setLayout(no_wallet_layout); walletStack->addWidget(no_wallet_group); + + m_page_pairing = new PairingPage(this); + m_global_stack->addWidget(m_page_pairing); } WalletFrame::~WalletFrame() = default; @@ -61,6 +67,8 @@ void WalletFrame::setClientModel(ClientModel *_clientModel) { this->clientModel = _clientModel; + m_page_pairing->setClientModel(_clientModel); + for (auto i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) { i.value()->setClientModel(_clientModel); } @@ -153,6 +161,12 @@ void WalletFrame::gotoOverviewPage() QMap::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoOverviewPage(); + m_global_stack->setCurrentWidget(walletStack); +} + +void WalletFrame::gotoPairingPage() +{ + m_global_stack->setCurrentWidget(m_page_pairing); } void WalletFrame::gotoHistoryPage() @@ -160,6 +174,7 @@ void WalletFrame::gotoHistoryPage() QMap::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoHistoryPage(); + m_global_stack->setCurrentWidget(walletStack); } void WalletFrame::gotoReceiveCoinsPage() @@ -167,6 +182,7 @@ void WalletFrame::gotoReceiveCoinsPage() QMap::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoReceiveCoinsPage(); + m_global_stack->setCurrentWidget(walletStack); } void WalletFrame::gotoSendCoinsPage(QString addr) @@ -174,6 +190,7 @@ void WalletFrame::gotoSendCoinsPage(QString addr) QMap::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoSendCoinsPage(addr); + m_global_stack->setCurrentWidget(walletStack); } void WalletFrame::gotoSignMessageTab(QString addr) diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 60c97ff76a..2760714cd4 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -9,6 +9,7 @@ #include class ClientModel; +class PairingPage; class PlatformStyle; class SendCoinsRecipient; class WalletModel; @@ -52,10 +53,13 @@ Q_SIGNALS: void currentWalletSet(); private: + QStackedWidget *m_global_stack; QStackedWidget *walletStack; ClientModel *clientModel; QMap mapWalletViews; + PairingPage *m_page_pairing; + bool bOutOfSync; const PlatformStyle *platformStyle; @@ -69,6 +73,8 @@ public: public Q_SLOTS: /** Switch to overview (home) page */ void gotoOverviewPage(); + /** Switch to pairing page */ + void gotoPairingPage(); /** Switch to history (transactions) page */ void gotoHistoryPage(); /** Switch to receive coins page */