1 // Copyright (c) 2011-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_QT_BITCOINGUI_H
6 #define BITCOIN_QT_BITCOINGUI_H
7 
8 #if defined(HAVE_CONFIG_H)
9 #include <config/bitcoin-config.h>
10 #endif
11 
12 #include <qt/guiutil.h>
13 #include <qt/optionsdialog.h>
14 
15 #include <amount.h>
16 
17 #include <QLabel>
18 #include <QMainWindow>
19 #include <QMap>
20 #include <QMenu>
21 #include <QPoint>
22 #include <QSystemTrayIcon>
23 
24 #ifdef Q_OS_MAC
25 #include <qt/macos_appnap.h>
26 #endif
27 
28 #include <memory>
29 
30 class ClientModel;
31 class NetworkStyle;
32 class Notificator;
33 class OptionsModel;
34 class PlatformStyle;
35 class RPCConsole;
36 class SendCoinsRecipient;
37 class UnitDisplayStatusBarControl;
38 class WalletController;
39 class WalletFrame;
40 class WalletModel;
41 class HelpMessageDialog;
42 class ModalOverlay;
43 enum class SynchronizationState;
44 
45 namespace interfaces {
46 class Handler;
47 class Node;
48 struct BlockAndHeaderTipInfo;
49 }
50 
51 QT_BEGIN_NAMESPACE
52 class QAction;
53 class QComboBox;
54 class QDateTime;
55 class QProgressBar;
56 class QProgressDialog;
57 QT_END_NAMESPACE
58 
59 namespace GUIUtil {
60 class ClickableLabel;
61 class ClickableProgressBar;
62 }
63 
64 /**
65   Bitcoin GUI main class. This class represents the main window of the Bitcoin UI. It communicates with both the client and
66   wallet models to give the user an up-to-date view of the current core state.
67 */
68 class BitcoinGUI : public QMainWindow
69 {
70     Q_OBJECT
71 
72 public:
73     static const std::string DEFAULT_UIPLATFORM;
74 
75     explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = nullptr);
76     ~BitcoinGUI();
77 
78     /** Set the client model.
79         The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
80     */
81     void setClientModel(ClientModel *clientModel = nullptr, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
82 #ifdef ENABLE_WALLET
83     void setWalletController(WalletController* wallet_controller);
84     WalletController* getWalletController();
85 #endif
86 
87 #ifdef ENABLE_WALLET
88     /** Set the wallet model.
89         The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
90         functionality.
91     */
92     void addWallet(WalletModel* walletModel);
93     void removeWallet(WalletModel* walletModel);
94     void removeAllWallets();
95 #endif // ENABLE_WALLET
96     bool enableWallet = false;
97 
98     /** Get the tray icon status.
99         Some systems have not "system tray" or "notification area" available.
100     */
hasTrayIcon()101     bool hasTrayIcon() const { return trayIcon; }
102 
103     /** Disconnect core signals from GUI client */
104     void unsubscribeFromCoreSignals();
105 
106     bool isPrivacyModeActivated() const;
107 
108 protected:
109     void changeEvent(QEvent *e) override;
110     void closeEvent(QCloseEvent *event) override;
111     void showEvent(QShowEvent *event) override;
112     void dragEnterEvent(QDragEnterEvent *event) override;
113     void dropEvent(QDropEvent *event) override;
114     bool eventFilter(QObject *object, QEvent *event) override;
115 
116 private:
117     interfaces::Node& m_node;
118     WalletController* m_wallet_controller{nullptr};
119     std::unique_ptr<interfaces::Handler> m_handler_message_box;
120     std::unique_ptr<interfaces::Handler> m_handler_question;
121     ClientModel* clientModel = nullptr;
122     WalletFrame* walletFrame = nullptr;
123 
124     UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
125     GUIUtil::ThemedLabel* labelWalletEncryptionIcon = nullptr;
126     GUIUtil::ThemedLabel* labelWalletHDStatusIcon = nullptr;
127     GUIUtil::ClickableLabel* labelProxyIcon = nullptr;
128     GUIUtil::ClickableLabel* connectionsControl = nullptr;
129     GUIUtil::ClickableLabel* labelBlocksIcon = nullptr;
130     QLabel* progressBarLabel = nullptr;
131     GUIUtil::ClickableProgressBar* progressBar = nullptr;
132     QProgressDialog* progressDialog = nullptr;
133 
134     QMenuBar* appMenuBar = nullptr;
135     QToolBar* appToolBar = nullptr;
136     QAction* overviewAction = nullptr;
137     QAction* historyAction = nullptr;
138     QAction* quitAction = nullptr;
139     QAction* sendCoinsAction = nullptr;
140     QAction* sendCoinsMenuAction = nullptr;
141     QAction* usedSendingAddressesAction = nullptr;
142     QAction* usedReceivingAddressesAction = nullptr;
143     QAction* signMessageAction = nullptr;
144     QAction* verifyMessageAction = nullptr;
145     QAction* m_load_psbt_action = nullptr;
146     QAction* m_load_psbt_clipboard_action = nullptr;
147     QAction* aboutAction = nullptr;
148     QAction* receiveCoinsAction = nullptr;
149     QAction* receiveCoinsMenuAction = nullptr;
150     QAction* optionsAction = nullptr;
151     QAction* toggleHideAction = nullptr;
152     QAction* encryptWalletAction = nullptr;
153     QAction* backupWalletAction = nullptr;
154     QAction* changePassphraseAction = nullptr;
155     QAction* aboutQtAction = nullptr;
156     QAction* openRPCConsoleAction = nullptr;
157     QAction* openAction = nullptr;
158     QAction* showHelpMessageAction = nullptr;
159     QAction* m_create_wallet_action{nullptr};
160     QAction* m_open_wallet_action{nullptr};
161     QMenu* m_open_wallet_menu{nullptr};
162     QAction* m_close_wallet_action{nullptr};
163     QAction* m_close_all_wallets_action{nullptr};
164     QAction* m_wallet_selector_label_action = nullptr;
165     QAction* m_wallet_selector_action = nullptr;
166     QAction* m_mask_values_action{nullptr};
167 
168     QLabel *m_wallet_selector_label = nullptr;
169     QComboBox* m_wallet_selector = nullptr;
170 
171     QSystemTrayIcon* trayIcon = nullptr;
172     const std::unique_ptr<QMenu> trayIconMenu;
173     Notificator* notificator = nullptr;
174     RPCConsole* rpcConsole = nullptr;
175     HelpMessageDialog* helpMessageDialog = nullptr;
176     ModalOverlay* modalOverlay = nullptr;
177 
178     QMenu* m_network_context_menu = new QMenu(this);
179 
180 #ifdef Q_OS_MAC
181     CAppNapInhibitor* m_app_nap_inhibitor = nullptr;
182 #endif
183 
184     /** Keep track of previous number of blocks, to detect progress */
185     int prevBlocks = 0;
186     int spinnerFrame = 0;
187 
188     const PlatformStyle *platformStyle;
189     const NetworkStyle* const m_network_style;
190 
191     /** Create the main UI actions. */
192     void createActions();
193     /** Create the menu bar and sub-menus. */
194     void createMenuBar();
195     /** Create the toolbars */
196     void createToolBars();
197     /** Create system tray icon and notification */
198     void createTrayIcon();
199     /** Create system tray menu (or setup the dock menu) */
200     void createTrayIconMenu();
201 
202     /** Enable or disable all wallet-related actions */
203     void setWalletActionsEnabled(bool enabled);
204 
205     /** Connect core signals to GUI client */
206     void subscribeToCoreSignals();
207 
208     /** Update UI with latest network info from model. */
209     void updateNetworkState();
210 
211     void updateHeadersSyncProgressLabel();
212 
213     /** Open the OptionsDialog on the specified tab index */
214     void openOptionsDialogWithTab(OptionsDialog::Tab tab);
215 
216 Q_SIGNALS:
217     /** Signal raised when a URI was entered or dragged to the GUI */
218     void receivedURI(const QString &uri);
219     /** Signal raised when RPC console shown */
220     void consoleShown(RPCConsole* console);
221     void setPrivacy(bool privacy);
222 
223 public Q_SLOTS:
224     /** Set number of connections shown in the UI */
225     void setNumConnections(int count);
226     /** Set network state shown in the UI */
227     void setNetworkActive(bool network_active);
228     /** Set number of blocks and last block date shown in the UI */
229     void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state);
230 
231     /** Notify the user of an event from the core network or transaction handling code.
232        @param[in] title             the message box / notification title
233        @param[in] message           the displayed text
234        @param[in] style             modality and style definitions (icon and used buttons - buttons only for message boxes)
235                                     @see CClientUIInterface::MessageBoxFlags
236        @param[in] ret               pointer to a bool that will be modified to whether Ok was clicked (modal only)
237        @param[in] detailed_message  the text to be displayed in the details area
238     */
239     void message(const QString& title, QString message, unsigned int style, bool* ret = nullptr, const QString& detailed_message = QString());
240 
241 #ifdef ENABLE_WALLET
242     void setCurrentWallet(WalletModel* wallet_model);
243     void setCurrentWalletBySelectorIndex(int index);
244     /** Set the UI status indicators based on the currently selected wallet.
245     */
246     void updateWalletStatus();
247 
248 private:
249     /** Set the encryption status as shown in the UI.
250        @param[in] status            current encryption status
251        @see WalletModel::EncryptionStatus
252     */
253     void setEncryptionStatus(int status);
254 
255     /** Set the hd-enabled status as shown in the UI.
256      @param[in] hdEnabled         current hd enabled status
257      @see WalletModel::EncryptionStatus
258      */
259     void setHDStatus(bool privkeyDisabled, int hdEnabled);
260 
261 public Q_SLOTS:
262     bool handlePaymentRequest(const SendCoinsRecipient& recipient);
263 
264     /** Show incoming transaction notification for new transactions. */
265     void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
266 #endif // ENABLE_WALLET
267 
268 private:
269     /** Set the proxy-enabled icon as shown in the UI. */
270     void updateProxyIcon();
271     void updateWindowTitle();
272 
273 public Q_SLOTS:
274 #ifdef ENABLE_WALLET
275     /** Switch to overview (home) page */
276     void gotoOverviewPage();
277     /** Switch to history (transactions) page */
278     void gotoHistoryPage();
279     /** Switch to receive coins page */
280     void gotoReceiveCoinsPage();
281     /** Switch to send coins page */
282     void gotoSendCoinsPage(QString addr = "");
283 
284     /** Show Sign/Verify Message dialog and switch to sign message tab */
285     void gotoSignMessageTab(QString addr = "");
286     /** Show Sign/Verify Message dialog and switch to verify message tab */
287     void gotoVerifyMessageTab(QString addr = "");
288     /** Load Partially Signed Bitcoin Transaction from file or clipboard */
289     void gotoLoadPSBT(bool from_clipboard = false);
290 
291     /** Show open dialog */
292     void openClicked();
293 #endif // ENABLE_WALLET
294     /** Show configuration dialog */
295     void optionsClicked();
296     /** Show about dialog */
297     void aboutClicked();
298     /** Show debug window */
299     void showDebugWindow();
300     /** Show debug window and set focus to the console */
301     void showDebugWindowActivateConsole();
302     /** Show help message dialog */
303     void showHelpMessageClicked();
304 #ifndef Q_OS_MAC
305     /** Handle tray icon clicked */
306     void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
307 #else
308     /** Handle macOS Dock icon clicked */
309     void macosDockIconActivated();
310 #endif
311 
312     /** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
showNormalIfMinimized()313     void showNormalIfMinimized() { showNormalIfMinimized(false); }
314     void showNormalIfMinimized(bool fToggleHidden);
315     /** Simply calls showNormalIfMinimized(true) for use in SLOT() macro */
316     void toggleHidden();
317 
318     /** called by a timer to check if ShutdownRequested() has been set **/
319     void detectShutdown();
320 
321     /** Show progress dialog e.g. for verifychain */
322     void showProgress(const QString &title, int nProgress);
323 
324     void showModalOverlay();
325 };
326 
327 class UnitDisplayStatusBarControl : public QLabel
328 {
329     Q_OBJECT
330 
331 public:
332     explicit UnitDisplayStatusBarControl(const PlatformStyle *platformStyle);
333     /** Lets the control know about the Options Model (and its signals) */
334     void setOptionsModel(OptionsModel *optionsModel);
335 
336 protected:
337     /** So that it responds to left-button clicks */
338     void mousePressEvent(QMouseEvent *event) override;
339     void changeEvent(QEvent* e) override;
340 
341 private:
342     OptionsModel *optionsModel;
343     QMenu* menu;
344     const PlatformStyle* m_platform_style;
345 
346     /** Shows context menu with Display Unit options by the mouse coordinates */
347     void onDisplayUnitsClicked(const QPoint& point);
348     /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
349     void createContextMenu();
350 
351 private Q_SLOTS:
352     /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
353     void updateDisplayUnit(int newUnits);
354     /** Tells underlying optionsModel to update its current display unit. */
355     void onMenuSelection(QAction* action);
356 };
357 
358 #endif // BITCOIN_QT_BITCOINGUI_H
359