text: // Copyright (c) 2011-2019 The Bitcoin Core developers
  // Copyright (c) 2019-2020 The Blocknet developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #ifndef BITCOIN_QT_BITCOINGUI_H
  #define BITCOIN_QT_BITCOINGUI_H
  
  #if defined(HAVE_CONFIG_H)
  #include <config/bitcoin-config.h>
  #endif
  
  #include <qt/optionsdialog.h>
  
  #include <amount.h>
  
  #include <QLabel>
  #include <QMainWindow>
  #include <QMap>
  #include <QPoint>
  #include <QSystemTrayIcon>
  
  #ifdef Q_OS_MAC
  #include <qt/macos_appnap.h>
  #endif
  
  #include <memory>
  
  class ClientModel;
  class NetworkStyle;
  class Notificator;
  class OptionsModel;
  class PlatformStyle;
  class RPCConsole;
  class SendCoinsRecipient;
  class UnitDisplayStatusBarControl;
  class WalletController;
  class WalletFrame;
  class WalletModel;
  class HelpMessageDialog;
  class ModalOverlay;
  
  namespace interfaces {
  class Handler;
  class Node;
  }
  
  QT_BEGIN_NAMESPACE
  class QAction;
  class QComboBox;
  class QMenu;
  class QProgressBar;
  class QProgressDialog;
  QT_END_NAMESPACE
  
  namespace GUIUtil {
  class ClickableLabel;
  class ClickableProgressBar;
  }
  
  class BitcoinGUIObj : public QMainWindow {
      Q_OBJECT
  public:
      explicit BitcoinGUIObj(QWidget *parent=nullptr) : QMainWindow(parent) {}
      ~BitcoinGUIObj() {}
      virtual void setClientModel(ClientModel *clientModel) = 0;
  #ifdef ENABLE_WALLET
      virtual void setWalletController(WalletController* wallet_controller) = 0;
      virtual void addWallet(WalletModel* walletModel) = 0;
      virtual void removeWallet(WalletModel* walletModel) = 0;
      virtual void removeAllWallets() = 0;
  #endif // ENABLE_WALLET
      virtual bool hasTrayIcon() const = 0;
      virtual void unsubscribeFromCoreSignals() = 0;
  
  protected:
      virtual void changeEvent(QEvent *e) = 0;
      virtual void closeEvent(QCloseEvent *event) = 0;
      virtual void showEvent(QShowEvent *event) = 0;
      virtual void dragEnterEvent(QDragEnterEvent *event) = 0;
      virtual void dropEvent(QDropEvent *event) = 0;
      virtual bool eventFilter(QObject *object, QEvent *event) = 0;
      virtual void createActions() = 0;
      virtual void createMenuBar() = 0;
      virtual void createToolBars() = 0;
      virtual void createTrayIcon() = 0;
      virtual void createTrayIconMenu() = 0;
      virtual void setWalletActionsEnabled(bool enabled) = 0;
      virtual void subscribeToCoreSignals() = 0;
      virtual void updateNetworkState() = 0;
      virtual void updateHeadersSyncProgressLabel() = 0;
      virtual void openOptionsDialogWithTab(OptionsDialog::Tab tab) = 0;
  
  Q_SIGNALS:
      void receivedURI(const QString &uri);
      void consoleShown(RPCConsole* console);
  
  public Q_SLOTS:
      virtual void setNumConnections(int count) = 0;
      virtual void setNetworkActive(bool networkActive) = 0;
      virtual void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers) = 0;
      virtual void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr) = 0;
  
  #ifdef ENABLE_WALLET
      virtual void setCurrentWallet(WalletModel* wallet_model) = 0;
      virtual void setCurrentWalletBySelectorIndex(int index) = 0;
      virtual void updateWalletStatus() = 0;
  
  protected:
      virtual void setEncryptionStatus(int status) = 0;
      virtual void setHDStatus(bool privkeyDisabled, int hdEnabled) = 0;
  
  public Q_SLOTS:
      virtual bool handlePaymentRequest(const SendCoinsRecipient& recipient) = 0;
      virtual void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName) = 0;
  #endif // ENABLE_WALLET
  
  protected:
      virtual void updateProxyIcon() = 0;
      virtual void updateWindowTitle() = 0;
  
  public Q_SLOTS:
  #ifdef ENABLE_WALLET
      virtual void gotoOverviewPage() = 0;
      virtual void gotoHistoryPage() = 0;
      virtual void gotoReceiveCoinsPage() = 0;
      virtual void gotoSendCoinsPage(QString addr = "") = 0;
      virtual void gotoSignMessageTab(QString addr = "") = 0;
      virtual void gotoVerifyMessageTab(QString addr = "") = 0;
      virtual void openClicked() = 0;
  #endif // ENABLE_WALLET
      virtual void optionsClicked() = 0;
      virtual void aboutClicked() = 0;
      virtual void showDebugWindow() = 0;
      virtual void showDebugWindowActivateConsole() = 0;
      virtual void showHelpMessageClicked() = 0;
  #ifndef Q_OS_MAC
      virtual void trayIconActivated(QSystemTrayIcon::ActivationReason reason) = 0;
  #else
      virtual void macosDockIconActivated() = 0;
  #endif
      virtual void showNormalIfMinimized() = 0;
      virtual void showNormalIfMinimized(bool fToggleHidden) = 0;
      virtual void toggleHidden() = 0;
      virtual void detectShutdown() = 0;
      virtual void showProgress(const QString &title, int nProgress) = 0;
      virtual void setTrayIconVisible(bool) = 0;
      virtual void showModalOverlay() = 0;
  };
  
  /**
    Bitcoin GUI main class. This class represents the main window of the Bitcoin UI. It communicates with both the client and
    wallet models to give the user an up-to-date view of the current core state.
  */
  class BitcoinGUI : public BitcoinGUIObj
  {
      Q_OBJECT
  
  public:
      static const std::string DEFAULT_UIPLATFORM;
  
      explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = nullptr);
      ~BitcoinGUI();
  
      /** Set the client model.
          The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
      */
      void setClientModel(ClientModel *clientModel);
  #ifdef ENABLE_WALLET
      void setWalletController(WalletController* wallet_controller);
  #endif
  
  #ifdef ENABLE_WALLET
      /** Set the wallet model.
          The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
          functionality.
      */
      void addWallet(WalletModel* walletModel);
      void removeWallet(WalletModel* walletModel);
      void removeAllWallets();
  #endif // ENABLE_WALLET
      bool enableWallet = false;
  
      /** Get the tray icon status.
          Some systems have not "system tray" or "notification area" available.
      */
      bool hasTrayIcon() const { return trayIcon; }
  
      /** Disconnect core signals from GUI client */
      void unsubscribeFromCoreSignals();
  
  protected:
      void changeEvent(QEvent *e);
      void closeEvent(QCloseEvent *event);
      void showEvent(QShowEvent *event);
      void dragEnterEvent(QDragEnterEvent *event);
      void dropEvent(QDropEvent *event);
      bool eventFilter(QObject *object, QEvent *event);
  
  private:
      interfaces::Node& m_node;
      WalletController* m_wallet_controller{nullptr};
      std::unique_ptr<interfaces::Handler> m_handler_message_box;
      std::unique_ptr<interfaces::Handler> m_handler_question;
      ClientModel* clientModel = nullptr;
      WalletFrame* walletFrame = nullptr;
  
      UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
      QLabel* labelWalletEncryptionIcon = nullptr;
      QLabel* labelWalletHDStatusIcon = nullptr;
      GUIUtil::ClickableLabel* labelProxyIcon = nullptr;
      GUIUtil::ClickableLabel* connectionsControl = nullptr;
      GUIUtil::ClickableLabel* labelBlocksIcon = nullptr;
      QLabel* progressBarLabel = nullptr;
      GUIUtil::ClickableProgressBar* progressBar = nullptr;
      QProgressDialog* progressDialog = nullptr;
  
      QMenuBar* appMenuBar = nullptr;
      QToolBar* appToolBar = nullptr;
      QAction* overviewAction = nullptr;
      QAction* historyAction = nullptr;
      QAction* quitAction = nullptr;
      QAction* sendCoinsAction = nullptr;
      QAction* sendCoinsMenuAction = nullptr;
      QAction* usedSendingAddressesAction = nullptr;
      QAction* usedReceivingAddressesAction = nullptr;
      QAction* signMessageAction = nullptr;
      QAction* verifyMessageAction = nullptr;
      QAction* aboutAction = nullptr;
      QAction* receiveCoinsAction = nullptr;
      QAction* receiveCoinsMenuAction = nullptr;
      QAction* optionsAction = nullptr;
      QAction* toggleHideAction = nullptr;
      QAction* encryptWalletAction = nullptr;
      QAction* backupWalletAction = nullptr;
      QAction* changePassphraseAction = nullptr;
      QAction* aboutQtAction = nullptr;
      QAction* openRPCConsoleAction = nullptr;
      QAction* openAction = nullptr;
      QAction* showHelpMessageAction = nullptr;
      QAction* m_open_wallet_action{nullptr};
      QAction* m_close_wallet_action{nullptr};
      QAction* m_wallet_selector_label_action = nullptr;
      QAction* m_wallet_selector_action = nullptr;
  
      QLabel *m_wallet_selector_label = nullptr;
      QComboBox* m_wallet_selector = nullptr;
  
      QSystemTrayIcon* trayIcon = nullptr;
      const std::unique_ptr<QMenu> trayIconMenu;
      Notificator* notificator = nullptr;
      RPCConsole* rpcConsole = nullptr;
      HelpMessageDialog* helpMessageDialog = nullptr;
      ModalOverlay* modalOverlay = nullptr;
  
  #ifdef Q_OS_MAC
      CAppNapInhibitor* m_app_nap_inhibitor = nullptr;
  #endif
  
      /** Keep track of previous number of blocks, to detect progress */
      int prevBlocks = 0;
      int spinnerFrame = 0;
  
      const PlatformStyle *platformStyle;
      const NetworkStyle* const m_network_style;
  
      /** Create the main UI actions. */
      void createActions();
      /** Create the menu bar and sub-menus. */
      void createMenuBar();
      /** Create the toolbars */
      void createToolBars();
      /** Create system tray icon and notification */
      void createTrayIcon();
      /** Create system tray menu (or setup the dock menu) */
      void createTrayIconMenu();
  
      /** Enable or disable all wallet-related actions */
      void setWalletActionsEnabled(bool enabled);
  
      /** Connect core signals to GUI client */
      void subscribeToCoreSignals();
  
      /** Update UI with latest network info from model. */
      void updateNetworkState();
  
      void updateHeadersSyncProgressLabel();
  
      /** Open the OptionsDialog on the specified tab index */
      void openOptionsDialogWithTab(OptionsDialog::Tab tab);
  
  Q_SIGNALS:
      /** Signal raised when a URI was entered or dragged to the GUI */
      void receivedURI(const QString &uri);
      /** Signal raised when RPC console shown */
      void consoleShown(RPCConsole* console);
  
  public Q_SLOTS:
      /** Set number of connections shown in the UI */
      void setNumConnections(int count);
      /** Set network state shown in the UI */
      void setNetworkActive(bool networkActive);
      /** Set number of blocks and last block date shown in the UI */
      void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers);
  
      /** Notify the user of an event from the core network or transaction handling code.
         @param[in] title     the message box / notification title
         @param[in] message   the displayed text
         @param[in] style     modality and style definitions (icon and used buttons - buttons only for message boxes)
                              @see CClientUIInterface::MessageBoxFlags
         @param[in] ret       pointer to a bool that will be modified to whether Ok was clicked (modal only)
      */
      void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
  
  #ifdef ENABLE_WALLET
      void setCurrentWallet(WalletModel* wallet_model);
      void setCurrentWalletBySelectorIndex(int index);
      /** 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
      */
      void setEncryptionStatus(int status);
  
      /** Set the hd-enabled status as shown in the UI.
       @param[in] hdEnabled         current hd enabled status
       @see WalletModel::EncryptionStatus
       */
      void setHDStatus(bool privkeyDisabled, 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, const QString& walletName);
  #endif // ENABLE_WALLET
  
  private:
      /** Set the proxy-enabled icon as shown in the UI. */
      void updateProxyIcon();
      void updateWindowTitle();
  
  public Q_SLOTS:
  #ifdef ENABLE_WALLET
      /** Switch to overview (home) page */
      void gotoOverviewPage();
      /** Switch to history (transactions) page */
      void gotoHistoryPage();
      /** Switch to receive coins page */
      void gotoReceiveCoinsPage();
      /** Switch to send coins page */
      void gotoSendCoinsPage(QString addr = "");
  
      /** Show Sign/Verify Message dialog and switch to sign message tab */
      void gotoSignMessageTab(QString addr = "");
      /** Show Sign/Verify Message dialog and switch to verify message tab */
      void gotoVerifyMessageTab(QString addr = "");
  
      /** Show open dialog */
      void openClicked();
  #endif // ENABLE_WALLET
      /** Show configuration dialog */
      void optionsClicked();
      /** Show about dialog */
      void aboutClicked();
      /** Show debug window */
      void showDebugWindow();
      /** Show debug window and set focus to the console */
      void showDebugWindowActivateConsole();
      /** Show help message dialog */
      void showHelpMessageClicked();
  #ifndef Q_OS_MAC
      /** Handle tray icon clicked */
      void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
  #else
      /** Handle macOS Dock icon clicked */
      void macosDockIconActivated();
  #endif
  
      /** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
      void showNormalIfMinimized() { showNormalIfMinimized(false); }
      void showNormalIfMinimized(bool fToggleHidden);
      /** Simply calls showNormalIfMinimized(true) for use in SLOT() macro */
      void toggleHidden();
  
      /** called by a timer to check if ShutdownRequested() has been set **/
      void detectShutdown();
  
      /** Show progress dialog e.g. for verifychain */
      void showProgress(const QString &title, int nProgress);
  
      /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */
      void setTrayIconVisible(bool);
  
      void showModalOverlay();
  };
  
  class UnitDisplayStatusBarControl : public QLabel
  {
      Q_OBJECT
  
  public:
      explicit UnitDisplayStatusBarControl(const PlatformStyle *platformStyle);
      /** Lets the control know about the Options Model (and its signals) */
      void setOptionsModel(OptionsModel *optionsModel);
  
  protected:
      /** So that it responds to left-button clicks */
      void mousePressEvent(QMouseEvent *event);
  
  private:
      OptionsModel *optionsModel;
      QMenu* menu;
  
      /** Shows context menu with Display Unit options by the mouse coordinates */
      void onDisplayUnitsClicked(const QPoint& point);
      /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
      void createContextMenu();
  
  private Q_SLOTS:
      /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
      void updateDisplayUnit(int newUnits);
      /** Tells underlying optionsModel to update its current display unit. */
      void onMenuSelection(QAction* action);
  };
  
  #endif // BITCOIN_QT_BITCOINGUI_H
  