Merge #11676: contrib/init: Update openrc-run filename
[bitcoinplatinum.git] / src / qt / bitcoingui.cpp
blobdc551419002a45aea838ec17596634e1d5f26218
1 // Copyright (c) 2011-2016 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.
5 #if defined(HAVE_CONFIG_H)
6 #include "config/bitcoin-config.h"
7 #endif
9 #include "bitcoingui.h"
11 #include "bitcoinunits.h"
12 #include "clientmodel.h"
13 #include "guiconstants.h"
14 #include "guiutil.h"
15 #include "modaloverlay.h"
16 #include "networkstyle.h"
17 #include "notificator.h"
18 #include "openuridialog.h"
19 #include "optionsdialog.h"
20 #include "optionsmodel.h"
21 #include "platformstyle.h"
22 #include "rpcconsole.h"
23 #include "utilitydialog.h"
25 #ifdef ENABLE_WALLET
26 #include "walletframe.h"
27 #include "walletmodel.h"
28 #endif // ENABLE_WALLET
30 #ifdef Q_OS_MAC
31 #include "macdockiconhandler.h"
32 #endif
34 #include "chainparams.h"
35 #include "init.h"
36 #include "ui_interface.h"
37 #include "util.h"
39 #include <iostream>
41 #include <QAction>
42 #include <QApplication>
43 #include <QDateTime>
44 #include <QDesktopWidget>
45 #include <QDragEnterEvent>
46 #include <QListWidget>
47 #include <QMenuBar>
48 #include <QMessageBox>
49 #include <QMimeData>
50 #include <QProgressDialog>
51 #include <QSettings>
52 #include <QShortcut>
53 #include <QStackedWidget>
54 #include <QStatusBar>
55 #include <QStyle>
56 #include <QTimer>
57 #include <QToolBar>
58 #include <QVBoxLayout>
60 #if QT_VERSION < 0x050000
61 #include <QTextDocument>
62 #include <QUrl>
63 #else
64 #include <QUrlQuery>
65 #endif
67 const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
68 #if defined(Q_OS_MAC)
69 "macosx"
70 #elif defined(Q_OS_WIN)
71 "windows"
72 #else
73 "other"
74 #endif
77 /** Display name for default wallet name. Uses tilde to avoid name
78 * collisions in the future with additional wallets */
79 const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
81 BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
82 QMainWindow(parent),
83 enableWallet(false),
84 clientModel(0),
85 walletFrame(0),
86 unitDisplayControl(0),
87 labelWalletEncryptionIcon(0),
88 labelWalletHDStatusIcon(0),
89 connectionsControl(0),
90 labelBlocksIcon(0),
91 progressBarLabel(0),
92 progressBar(0),
93 progressDialog(0),
94 appMenuBar(0),
95 overviewAction(0),
96 historyAction(0),
97 quitAction(0),
98 sendCoinsAction(0),
99 sendCoinsMenuAction(0),
100 usedSendingAddressesAction(0),
101 usedReceivingAddressesAction(0),
102 signMessageAction(0),
103 verifyMessageAction(0),
104 aboutAction(0),
105 receiveCoinsAction(0),
106 receiveCoinsMenuAction(0),
107 optionsAction(0),
108 toggleHideAction(0),
109 encryptWalletAction(0),
110 backupWalletAction(0),
111 changePassphraseAction(0),
112 aboutQtAction(0),
113 openRPCConsoleAction(0),
114 openAction(0),
115 showHelpMessageAction(0),
116 trayIcon(0),
117 trayIconMenu(0),
118 notificator(0),
119 rpcConsole(0),
120 helpMessageDialog(0),
121 modalOverlay(0),
122 prevBlocks(0),
123 spinnerFrame(0),
124 platformStyle(_platformStyle)
126 QSettings settings;
127 if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
128 // Restore failed (perhaps missing setting), center the window
129 move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
132 QString windowTitle = tr(PACKAGE_NAME) + " - ";
133 #ifdef ENABLE_WALLET
134 enableWallet = WalletModel::isWalletEnabled();
135 #endif // ENABLE_WALLET
136 if(enableWallet)
138 windowTitle += tr("Wallet");
139 } else {
140 windowTitle += tr("Node");
142 windowTitle += " " + networkStyle->getTitleAddText();
143 #ifndef Q_OS_MAC
144 QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
145 setWindowIcon(networkStyle->getTrayAndWindowIcon());
146 #else
147 MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
148 #endif
149 setWindowTitle(windowTitle);
151 #if defined(Q_OS_MAC) && QT_VERSION < 0x050000
152 // This property is not implemented in Qt 5. Setting it has no effect.
153 // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
154 setUnifiedTitleAndToolBarOnMac(true);
155 #endif
157 rpcConsole = new RPCConsole(_platformStyle, 0);
158 helpMessageDialog = new HelpMessageDialog(this, false);
159 #ifdef ENABLE_WALLET
160 if(enableWallet)
162 /** Create wallet frame and make it the central widget */
163 walletFrame = new WalletFrame(_platformStyle, this);
164 setCentralWidget(walletFrame);
165 } else
166 #endif // ENABLE_WALLET
168 /* When compiled without wallet or -disablewallet is provided,
169 * the central widget is the rpc console.
171 setCentralWidget(rpcConsole);
174 // Accept D&D of URIs
175 setAcceptDrops(true);
177 // Create actions for the toolbar, menu bar and tray/dock icon
178 // Needs walletFrame to be initialized
179 createActions();
181 // Create application menu bar
182 createMenuBar();
184 // Create the toolbars
185 createToolBars();
187 // Create system tray icon and notification
188 createTrayIcon(networkStyle);
190 // Create status bar
191 statusBar();
193 // Disable size grip because it looks ugly and nobody needs it
194 statusBar()->setSizeGripEnabled(false);
196 // Status bar notification icons
197 QFrame *frameBlocks = new QFrame();
198 frameBlocks->setContentsMargins(0,0,0,0);
199 frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
200 QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
201 frameBlocksLayout->setContentsMargins(3,0,3,0);
202 frameBlocksLayout->setSpacing(3);
203 unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
204 labelWalletEncryptionIcon = new QLabel();
205 labelWalletHDStatusIcon = new QLabel();
206 connectionsControl = new GUIUtil::ClickableLabel();
207 labelBlocksIcon = new GUIUtil::ClickableLabel();
208 if(enableWallet)
210 frameBlocksLayout->addStretch();
211 frameBlocksLayout->addWidget(unitDisplayControl);
212 frameBlocksLayout->addStretch();
213 frameBlocksLayout->addWidget(labelWalletEncryptionIcon);
214 frameBlocksLayout->addWidget(labelWalletHDStatusIcon);
216 frameBlocksLayout->addStretch();
217 frameBlocksLayout->addWidget(connectionsControl);
218 frameBlocksLayout->addStretch();
219 frameBlocksLayout->addWidget(labelBlocksIcon);
220 frameBlocksLayout->addStretch();
222 // Progress bar and label for blocks download
223 progressBarLabel = new QLabel();
224 progressBarLabel->setVisible(false);
225 progressBar = new GUIUtil::ProgressBar();
226 progressBar->setAlignment(Qt::AlignCenter);
227 progressBar->setVisible(false);
229 // Override style sheet for progress bar for styles that have a segmented progress bar,
230 // as they make the text unreadable (workaround for issue #1071)
231 // See https://qt-project.org/doc/qt-4.8/gallery.html
232 QString curStyle = QApplication::style()->metaObject()->className();
233 if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
235 progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }");
238 statusBar()->addWidget(progressBarLabel);
239 statusBar()->addWidget(progressBar);
240 statusBar()->addPermanentWidget(frameBlocks);
242 // Install event filter to be able to catch status tip events (QEvent::StatusTip)
243 this->installEventFilter(this);
245 // Initially wallet actions should be disabled
246 setWalletActionsEnabled(false);
248 // Subscribe to notifications from core
249 subscribeToCoreSignals();
251 connect(connectionsControl, SIGNAL(clicked(QPoint)), this, SLOT(toggleNetworkActive()));
253 modalOverlay = new ModalOverlay(this->centralWidget());
254 #ifdef ENABLE_WALLET
255 if(enableWallet) {
256 connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this, SLOT(showModalOverlay()));
257 connect(labelBlocksIcon, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
258 connect(progressBar, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
260 #endif
263 BitcoinGUI::~BitcoinGUI()
265 // Unsubscribe from notifications from core
266 unsubscribeFromCoreSignals();
268 QSettings settings;
269 settings.setValue("MainWindowGeometry", saveGeometry());
270 if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
271 trayIcon->hide();
272 #ifdef Q_OS_MAC
273 delete appMenuBar;
274 MacDockIconHandler::cleanup();
275 #endif
277 delete rpcConsole;
280 void BitcoinGUI::createActions()
282 QActionGroup *tabGroup = new QActionGroup(this);
284 overviewAction = new QAction(platformStyle->SingleColorIcon(":/icons/overview"), tr("&Overview"), this);
285 overviewAction->setStatusTip(tr("Show general overview of wallet"));
286 overviewAction->setToolTip(overviewAction->statusTip());
287 overviewAction->setCheckable(true);
288 overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
289 tabGroup->addAction(overviewAction);
291 sendCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/send"), tr("&Send"), this);
292 sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
293 sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
294 sendCoinsAction->setCheckable(true);
295 sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
296 tabGroup->addAction(sendCoinsAction);
298 sendCoinsMenuAction = new QAction(platformStyle->TextColorIcon(":/icons/send"), sendCoinsAction->text(), this);
299 sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
300 sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
302 receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
303 receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
304 receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
305 receiveCoinsAction->setCheckable(true);
306 receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
307 tabGroup->addAction(receiveCoinsAction);
309 receiveCoinsMenuAction = new QAction(platformStyle->TextColorIcon(":/icons/receiving_addresses"), receiveCoinsAction->text(), this);
310 receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
311 receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
313 historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
314 historyAction->setStatusTip(tr("Browse transaction history"));
315 historyAction->setToolTip(historyAction->statusTip());
316 historyAction->setCheckable(true);
317 historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
318 tabGroup->addAction(historyAction);
320 #ifdef ENABLE_WALLET
321 // These showNormalIfMinimized are needed because Send Coins and Receive Coins
322 // can be triggered from the tray menu, and need to show the GUI to be useful.
323 connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
324 connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
325 connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
326 connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
327 connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
328 connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
329 connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
330 connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
331 connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
332 connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
333 connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
334 connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
335 #endif // ENABLE_WALLET
337 quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this);
338 quitAction->setStatusTip(tr("Quit application"));
339 quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
340 quitAction->setMenuRole(QAction::QuitRole);
341 aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&About %1").arg(tr(PACKAGE_NAME)), this);
342 aboutAction->setStatusTip(tr("Show information about %1").arg(tr(PACKAGE_NAME)));
343 aboutAction->setMenuRole(QAction::AboutRole);
344 aboutAction->setEnabled(false);
345 aboutQtAction = new QAction(platformStyle->TextColorIcon(":/icons/about_qt"), tr("About &Qt"), this);
346 aboutQtAction->setStatusTip(tr("Show information about Qt"));
347 aboutQtAction->setMenuRole(QAction::AboutQtRole);
348 optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"), tr("&Options..."), this);
349 optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(tr(PACKAGE_NAME)));
350 optionsAction->setMenuRole(QAction::PreferencesRole);
351 optionsAction->setEnabled(false);
352 toggleHideAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&Show / Hide"), this);
353 toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
355 encryptWalletAction = new QAction(platformStyle->TextColorIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
356 encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
357 encryptWalletAction->setCheckable(true);
358 backupWalletAction = new QAction(platformStyle->TextColorIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
359 backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
360 changePassphraseAction = new QAction(platformStyle->TextColorIcon(":/icons/key"), tr("&Change Passphrase..."), this);
361 changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
362 signMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/edit"), tr("Sign &message..."), this);
363 signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
364 verifyMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/verify"), tr("&Verify message..."), this);
365 verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
367 openRPCConsoleAction = new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"), tr("&Debug window"), this);
368 openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
369 // initially disable the debug window menu item
370 openRPCConsoleAction->setEnabled(false);
372 usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
373 usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
374 usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
375 usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
377 openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
378 openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
380 showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
381 showHelpMessageAction->setMenuRole(QAction::NoRole);
382 showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(tr(PACKAGE_NAME)));
384 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
385 connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
386 connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
387 connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
388 connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
389 connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
390 connect(openRPCConsoleAction, SIGNAL(triggered()), this, SLOT(showDebugWindow()));
391 // prevents an open debug window from becoming stuck/unusable on client shutdown
392 connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
394 #ifdef ENABLE_WALLET
395 if(walletFrame)
397 connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
398 connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
399 connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
400 connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
401 connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
402 connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
403 connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
404 connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
406 #endif // ENABLE_WALLET
408 new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this, SLOT(showDebugWindowActivateConsole()));
409 new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this, SLOT(showDebugWindow()));
412 void BitcoinGUI::createMenuBar()
414 #ifdef Q_OS_MAC
415 // Create a decoupled menu bar on Mac which stays even if the window is closed
416 appMenuBar = new QMenuBar();
417 #else
418 // Get the main window's menu bar on other platforms
419 appMenuBar = menuBar();
420 #endif
422 // Configure the menus
423 QMenu *file = appMenuBar->addMenu(tr("&File"));
424 if(walletFrame)
426 file->addAction(openAction);
427 file->addAction(backupWalletAction);
428 file->addAction(signMessageAction);
429 file->addAction(verifyMessageAction);
430 file->addSeparator();
431 file->addAction(usedSendingAddressesAction);
432 file->addAction(usedReceivingAddressesAction);
433 file->addSeparator();
435 file->addAction(quitAction);
437 QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
438 if(walletFrame)
440 settings->addAction(encryptWalletAction);
441 settings->addAction(changePassphraseAction);
442 settings->addSeparator();
444 settings->addAction(optionsAction);
446 QMenu *help = appMenuBar->addMenu(tr("&Help"));
447 if(walletFrame)
449 help->addAction(openRPCConsoleAction);
451 help->addAction(showHelpMessageAction);
452 help->addSeparator();
453 help->addAction(aboutAction);
454 help->addAction(aboutQtAction);
457 void BitcoinGUI::createToolBars()
459 if(walletFrame)
461 QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
462 toolbar->setContextMenuPolicy(Qt::PreventContextMenu);
463 toolbar->setMovable(false);
464 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
465 toolbar->addAction(overviewAction);
466 toolbar->addAction(sendCoinsAction);
467 toolbar->addAction(receiveCoinsAction);
468 toolbar->addAction(historyAction);
469 overviewAction->setChecked(true);
473 void BitcoinGUI::setClientModel(ClientModel *_clientModel)
475 this->clientModel = _clientModel;
476 if(_clientModel)
478 // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
479 // while the client has not yet fully loaded
480 createTrayIconMenu();
482 // Keep up to date with client
483 updateNetworkState();
484 connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
485 connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
487 modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
488 setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(nullptr), false);
489 connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
491 // Receive and report messages from client model
492 connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
494 // Show progress dialog
495 connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
497 rpcConsole->setClientModel(_clientModel);
498 #ifdef ENABLE_WALLET
499 if(walletFrame)
501 walletFrame->setClientModel(_clientModel);
503 #endif // ENABLE_WALLET
504 unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
506 OptionsModel* optionsModel = _clientModel->getOptionsModel();
507 if(optionsModel)
509 // be aware of the tray icon disable state change reported by the OptionsModel object.
510 connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool)));
512 // initialize the disable state of the tray icon with the current value in the model.
513 setTrayIconVisible(optionsModel->getHideTrayIcon());
515 } else {
516 // Disable possibility to show main window via action
517 toggleHideAction->setEnabled(false);
518 if(trayIconMenu)
520 // Disable context menu on tray icon
521 trayIconMenu->clear();
523 // Propagate cleared model to child objects
524 rpcConsole->setClientModel(nullptr);
525 #ifdef ENABLE_WALLET
526 if (walletFrame)
528 walletFrame->setClientModel(nullptr);
530 #endif // ENABLE_WALLET
531 unitDisplayControl->setOptionsModel(nullptr);
535 #ifdef ENABLE_WALLET
536 bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
538 if(!walletFrame)
539 return false;
540 setWalletActionsEnabled(true);
541 return walletFrame->addWallet(name, walletModel);
544 bool BitcoinGUI::setCurrentWallet(const QString& name)
546 if(!walletFrame)
547 return false;
548 return walletFrame->setCurrentWallet(name);
551 void BitcoinGUI::removeAllWallets()
553 if(!walletFrame)
554 return;
555 setWalletActionsEnabled(false);
556 walletFrame->removeAllWallets();
558 #endif // ENABLE_WALLET
560 void BitcoinGUI::setWalletActionsEnabled(bool enabled)
562 overviewAction->setEnabled(enabled);
563 sendCoinsAction->setEnabled(enabled);
564 sendCoinsMenuAction->setEnabled(enabled);
565 receiveCoinsAction->setEnabled(enabled);
566 receiveCoinsMenuAction->setEnabled(enabled);
567 historyAction->setEnabled(enabled);
568 encryptWalletAction->setEnabled(enabled);
569 backupWalletAction->setEnabled(enabled);
570 changePassphraseAction->setEnabled(enabled);
571 signMessageAction->setEnabled(enabled);
572 verifyMessageAction->setEnabled(enabled);
573 usedSendingAddressesAction->setEnabled(enabled);
574 usedReceivingAddressesAction->setEnabled(enabled);
575 openAction->setEnabled(enabled);
578 void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
580 #ifndef Q_OS_MAC
581 trayIcon = new QSystemTrayIcon(this);
582 QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText();
583 trayIcon->setToolTip(toolTip);
584 trayIcon->setIcon(networkStyle->getTrayAndWindowIcon());
585 trayIcon->hide();
586 #endif
588 notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
591 void BitcoinGUI::createTrayIconMenu()
593 #ifndef Q_OS_MAC
594 // return if trayIcon is unset (only on non-Mac OSes)
595 if (!trayIcon)
596 return;
598 trayIconMenu = new QMenu(this);
599 trayIcon->setContextMenu(trayIconMenu);
601 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
602 this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
603 #else
604 // Note: On Mac, the dock icon is used to provide the tray's functionality.
605 MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
606 dockIconHandler->setMainWindow((QMainWindow *)this);
607 trayIconMenu = dockIconHandler->dockMenu();
608 #endif
610 // Configuration of the tray icon (or dock icon) icon menu
611 trayIconMenu->addAction(toggleHideAction);
612 trayIconMenu->addSeparator();
613 trayIconMenu->addAction(sendCoinsMenuAction);
614 trayIconMenu->addAction(receiveCoinsMenuAction);
615 trayIconMenu->addSeparator();
616 trayIconMenu->addAction(signMessageAction);
617 trayIconMenu->addAction(verifyMessageAction);
618 trayIconMenu->addSeparator();
619 trayIconMenu->addAction(optionsAction);
620 trayIconMenu->addAction(openRPCConsoleAction);
621 #ifndef Q_OS_MAC // This is built-in on Mac
622 trayIconMenu->addSeparator();
623 trayIconMenu->addAction(quitAction);
624 #endif
627 #ifndef Q_OS_MAC
628 void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
630 if(reason == QSystemTrayIcon::Trigger)
632 // Click on system tray icon triggers show/hide of the main window
633 toggleHidden();
636 #endif
638 void BitcoinGUI::optionsClicked()
640 if(!clientModel || !clientModel->getOptionsModel())
641 return;
643 OptionsDialog dlg(this, enableWallet);
644 dlg.setModel(clientModel->getOptionsModel());
645 dlg.exec();
648 void BitcoinGUI::aboutClicked()
650 if(!clientModel)
651 return;
653 HelpMessageDialog dlg(this, true);
654 dlg.exec();
657 void BitcoinGUI::showDebugWindow()
659 rpcConsole->showNormal();
660 rpcConsole->show();
661 rpcConsole->raise();
662 rpcConsole->activateWindow();
665 void BitcoinGUI::showDebugWindowActivateConsole()
667 rpcConsole->setTabFocus(RPCConsole::TAB_CONSOLE);
668 showDebugWindow();
671 void BitcoinGUI::showHelpMessageClicked()
673 helpMessageDialog->show();
676 #ifdef ENABLE_WALLET
677 void BitcoinGUI::openClicked()
679 OpenURIDialog dlg(this);
680 if(dlg.exec())
682 Q_EMIT receivedURI(dlg.getURI());
686 void BitcoinGUI::gotoOverviewPage()
688 overviewAction->setChecked(true);
689 if (walletFrame) walletFrame->gotoOverviewPage();
692 void BitcoinGUI::gotoHistoryPage()
694 historyAction->setChecked(true);
695 if (walletFrame) walletFrame->gotoHistoryPage();
698 void BitcoinGUI::gotoReceiveCoinsPage()
700 receiveCoinsAction->setChecked(true);
701 if (walletFrame) walletFrame->gotoReceiveCoinsPage();
704 void BitcoinGUI::gotoSendCoinsPage(QString addr)
706 sendCoinsAction->setChecked(true);
707 if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
710 void BitcoinGUI::gotoSignMessageTab(QString addr)
712 if (walletFrame) walletFrame->gotoSignMessageTab(addr);
715 void BitcoinGUI::gotoVerifyMessageTab(QString addr)
717 if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
719 #endif // ENABLE_WALLET
721 void BitcoinGUI::updateNetworkState()
723 int count = clientModel->getNumConnections();
724 QString icon;
725 switch(count)
727 case 0: icon = ":/icons/connect_0"; break;
728 case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
729 case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
730 case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
731 default: icon = ":/icons/connect_4"; break;
734 QString tooltip;
736 if (clientModel->getNetworkActive()) {
737 tooltip = tr("%n active connection(s) to Bitcoin network", "", count) + QString(".<br>") + tr("Click to disable network activity.");
738 } else {
739 tooltip = tr("Network activity disabled.") + QString("<br>") + tr("Click to enable network activity again.");
740 icon = ":/icons/network_disabled";
743 // Don't word-wrap this (fixed-width) tooltip
744 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
745 connectionsControl->setToolTip(tooltip);
747 connectionsControl->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
750 void BitcoinGUI::setNumConnections(int count)
752 updateNetworkState();
755 void BitcoinGUI::setNetworkActive(bool networkActive)
757 updateNetworkState();
760 void BitcoinGUI::updateHeadersSyncProgressLabel()
762 int64_t headersTipTime = clientModel->getHeaderTipTime();
763 int headersTipHeight = clientModel->getHeaderTipHeight();
764 int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing;
765 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
766 progressBarLabel->setText(tr("Syncing Headers (%1%)...").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
769 void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header)
771 if (modalOverlay)
773 if (header)
774 modalOverlay->setKnownBestHeight(count, blockDate);
775 else
776 modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
778 if (!clientModel)
779 return;
781 // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
782 statusBar()->clearMessage();
784 // Acquire current block source
785 enum BlockSource blockSource = clientModel->getBlockSource();
786 switch (blockSource) {
787 case BLOCK_SOURCE_NETWORK:
788 if (header) {
789 updateHeadersSyncProgressLabel();
790 return;
792 progressBarLabel->setText(tr("Synchronizing with network..."));
793 updateHeadersSyncProgressLabel();
794 break;
795 case BLOCK_SOURCE_DISK:
796 if (header) {
797 progressBarLabel->setText(tr("Indexing blocks on disk..."));
798 } else {
799 progressBarLabel->setText(tr("Processing blocks on disk..."));
801 break;
802 case BLOCK_SOURCE_REINDEX:
803 progressBarLabel->setText(tr("Reindexing blocks on disk..."));
804 break;
805 case BLOCK_SOURCE_NONE:
806 if (header) {
807 return;
809 progressBarLabel->setText(tr("Connecting to peers..."));
810 break;
813 QString tooltip;
815 QDateTime currentDate = QDateTime::currentDateTime();
816 qint64 secs = blockDate.secsTo(currentDate);
818 tooltip = tr("Processed %n block(s) of transaction history.", "", count);
820 // Set icon state: spinning if catching up, tick otherwise
821 if(secs < 90*60)
823 tooltip = tr("Up to date") + QString(".<br>") + tooltip;
824 labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
826 #ifdef ENABLE_WALLET
827 if(walletFrame)
829 walletFrame->showOutOfSyncWarning(false);
830 modalOverlay->showHide(true, true);
832 #endif // ENABLE_WALLET
834 progressBarLabel->setVisible(false);
835 progressBar->setVisible(false);
837 else
839 QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
841 progressBarLabel->setVisible(true);
842 progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
843 progressBar->setMaximum(1000000000);
844 progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
845 progressBar->setVisible(true);
847 tooltip = tr("Catching up...") + QString("<br>") + tooltip;
848 if(count != prevBlocks)
850 labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(QString(
851 ":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')))
852 .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
853 spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
855 prevBlocks = count;
857 #ifdef ENABLE_WALLET
858 if(walletFrame)
860 walletFrame->showOutOfSyncWarning(true);
861 modalOverlay->showHide();
863 #endif // ENABLE_WALLET
865 tooltip += QString("<br>");
866 tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
867 tooltip += QString("<br>");
868 tooltip += tr("Transactions after this will not yet be visible.");
871 // Don't word-wrap this (fixed-width) tooltip
872 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
874 labelBlocksIcon->setToolTip(tooltip);
875 progressBarLabel->setToolTip(tooltip);
876 progressBar->setToolTip(tooltip);
879 void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
881 QString strTitle = tr("Bitcoin"); // default title
882 // Default to information icon
883 int nMBoxIcon = QMessageBox::Information;
884 int nNotifyIcon = Notificator::Information;
886 QString msgType;
888 // Prefer supplied title over style based title
889 if (!title.isEmpty()) {
890 msgType = title;
892 else {
893 switch (style) {
894 case CClientUIInterface::MSG_ERROR:
895 msgType = tr("Error");
896 break;
897 case CClientUIInterface::MSG_WARNING:
898 msgType = tr("Warning");
899 break;
900 case CClientUIInterface::MSG_INFORMATION:
901 msgType = tr("Information");
902 break;
903 default:
904 break;
907 // Append title to "Bitcoin - "
908 if (!msgType.isEmpty())
909 strTitle += " - " + msgType;
911 // Check for error/warning icon
912 if (style & CClientUIInterface::ICON_ERROR) {
913 nMBoxIcon = QMessageBox::Critical;
914 nNotifyIcon = Notificator::Critical;
916 else if (style & CClientUIInterface::ICON_WARNING) {
917 nMBoxIcon = QMessageBox::Warning;
918 nNotifyIcon = Notificator::Warning;
921 // Display message
922 if (style & CClientUIInterface::MODAL) {
923 // Check for buttons, use OK as default, if none was supplied
924 QMessageBox::StandardButton buttons;
925 if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
926 buttons = QMessageBox::Ok;
928 showNormalIfMinimized();
929 QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
930 int r = mBox.exec();
931 if (ret != nullptr)
932 *ret = r == QMessageBox::Ok;
934 else
935 notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
938 void BitcoinGUI::changeEvent(QEvent *e)
940 QMainWindow::changeEvent(e);
941 #ifndef Q_OS_MAC // Ignored on Mac
942 if(e->type() == QEvent::WindowStateChange)
944 if(clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getMinimizeToTray())
946 QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
947 if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
949 QTimer::singleShot(0, this, SLOT(hide()));
950 e->ignore();
954 #endif
957 void BitcoinGUI::closeEvent(QCloseEvent *event)
959 #ifndef Q_OS_MAC // Ignored on Mac
960 if(clientModel && clientModel->getOptionsModel())
962 if(!clientModel->getOptionsModel()->getMinimizeOnClose())
964 // close rpcConsole in case it was open to make some space for the shutdown window
965 rpcConsole->close();
967 QApplication::quit();
969 else
971 QMainWindow::showMinimized();
972 event->ignore();
975 #else
976 QMainWindow::closeEvent(event);
977 #endif
980 void BitcoinGUI::showEvent(QShowEvent *event)
982 // enable the debug window when the main window shows up
983 openRPCConsoleAction->setEnabled(true);
984 aboutAction->setEnabled(true);
985 optionsAction->setEnabled(true);
988 #ifdef ENABLE_WALLET
989 void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
991 // On new transaction, make an info balloon
992 QString msg = tr("Date: %1\n").arg(date) +
993 tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) +
994 tr("Type: %1\n").arg(type);
995 if (!label.isEmpty())
996 msg += tr("Label: %1\n").arg(label);
997 else if (!address.isEmpty())
998 msg += tr("Address: %1\n").arg(address);
999 message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
1000 msg, CClientUIInterface::MSG_INFORMATION);
1002 #endif // ENABLE_WALLET
1004 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
1006 // Accept only URIs
1007 if(event->mimeData()->hasUrls())
1008 event->acceptProposedAction();
1011 void BitcoinGUI::dropEvent(QDropEvent *event)
1013 if(event->mimeData()->hasUrls())
1015 for (const QUrl &uri : event->mimeData()->urls())
1017 Q_EMIT receivedURI(uri.toString());
1020 event->acceptProposedAction();
1023 bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
1025 // Catch status tip events
1026 if (event->type() == QEvent::StatusTip)
1028 // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
1029 if (progressBarLabel->isVisible() || progressBar->isVisible())
1030 return true;
1032 return QMainWindow::eventFilter(object, event);
1035 #ifdef ENABLE_WALLET
1036 bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
1038 // URI has to be valid
1039 if (walletFrame && walletFrame->handlePaymentRequest(recipient))
1041 showNormalIfMinimized();
1042 gotoSendCoinsPage();
1043 return true;
1045 return false;
1048 void BitcoinGUI::setHDStatus(int hdEnabled)
1050 labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
1051 labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
1053 // eventually disable the QLabel to set its opacity to 50%
1054 labelWalletHDStatusIcon->setEnabled(hdEnabled);
1057 void BitcoinGUI::setEncryptionStatus(int status)
1059 switch(status)
1061 case WalletModel::Unencrypted:
1062 labelWalletEncryptionIcon->hide();
1063 encryptWalletAction->setChecked(false);
1064 changePassphraseAction->setEnabled(false);
1065 encryptWalletAction->setEnabled(true);
1066 break;
1067 case WalletModel::Unlocked:
1068 labelWalletEncryptionIcon->show();
1069 labelWalletEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
1070 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
1071 encryptWalletAction->setChecked(true);
1072 changePassphraseAction->setEnabled(true);
1073 encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
1074 break;
1075 case WalletModel::Locked:
1076 labelWalletEncryptionIcon->show();
1077 labelWalletEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
1078 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
1079 encryptWalletAction->setChecked(true);
1080 changePassphraseAction->setEnabled(true);
1081 encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
1082 break;
1085 #endif // ENABLE_WALLET
1087 void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
1089 if(!clientModel)
1090 return;
1092 // activateWindow() (sometimes) helps with keyboard focus on Windows
1093 if (isHidden())
1095 show();
1096 activateWindow();
1098 else if (isMinimized())
1100 showNormal();
1101 activateWindow();
1103 else if (GUIUtil::isObscured(this))
1105 raise();
1106 activateWindow();
1108 else if(fToggleHidden)
1109 hide();
1112 void BitcoinGUI::toggleHidden()
1114 showNormalIfMinimized(true);
1117 void BitcoinGUI::detectShutdown()
1119 if (ShutdownRequested())
1121 if(rpcConsole)
1122 rpcConsole->hide();
1123 qApp->quit();
1127 void BitcoinGUI::showProgress(const QString &title, int nProgress)
1129 if (nProgress == 0)
1131 progressDialog = new QProgressDialog(title, "", 0, 100);
1132 progressDialog->setWindowModality(Qt::ApplicationModal);
1133 progressDialog->setMinimumDuration(0);
1134 progressDialog->setCancelButton(0);
1135 progressDialog->setAutoClose(false);
1136 progressDialog->setValue(0);
1138 else if (nProgress == 100)
1140 if (progressDialog)
1142 progressDialog->close();
1143 progressDialog->deleteLater();
1146 else if (progressDialog)
1147 progressDialog->setValue(nProgress);
1150 void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon)
1152 if (trayIcon)
1154 trayIcon->setVisible(!fHideTrayIcon);
1158 void BitcoinGUI::showModalOverlay()
1160 if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
1161 modalOverlay->toggleVisibility();
1164 static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
1166 bool modal = (style & CClientUIInterface::MODAL);
1167 // The SECURE flag has no effect in the Qt GUI.
1168 // bool secure = (style & CClientUIInterface::SECURE);
1169 style &= ~CClientUIInterface::SECURE;
1170 bool ret = false;
1171 // In case of modal message, use blocking connection to wait for user to click a button
1172 QMetaObject::invokeMethod(gui, "message",
1173 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1174 Q_ARG(QString, QString::fromStdString(caption)),
1175 Q_ARG(QString, QString::fromStdString(message)),
1176 Q_ARG(unsigned int, style),
1177 Q_ARG(bool*, &ret));
1178 return ret;
1181 void BitcoinGUI::subscribeToCoreSignals()
1183 // Connect signals to client
1184 uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
1185 uiInterface.ThreadSafeQuestion.connect(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4));
1188 void BitcoinGUI::unsubscribeFromCoreSignals()
1190 // Disconnect signals from client
1191 uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
1192 uiInterface.ThreadSafeQuestion.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4));
1195 void BitcoinGUI::toggleNetworkActive()
1197 if (clientModel) {
1198 clientModel->setNetworkActive(!clientModel->getNetworkActive());
1202 UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
1203 optionsModel(0),
1204 menu(0)
1206 createContextMenu();
1207 setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1208 QList<BitcoinUnits::Unit> units = BitcoinUnits::availableUnits();
1209 int max_width = 0;
1210 const QFontMetrics fm(font());
1211 for (const BitcoinUnits::Unit unit : units)
1213 max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit)));
1215 setMinimumSize(max_width, 0);
1216 setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1217 setStyleSheet(QString("QLabel { color : %1 }").arg(platformStyle->SingleColor().name()));
1220 /** So that it responds to button clicks */
1221 void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
1223 onDisplayUnitsClicked(event->pos());
1226 /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
1227 void UnitDisplayStatusBarControl::createContextMenu()
1229 menu = new QMenu(this);
1230 for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
1232 QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
1233 menuAction->setData(QVariant(u));
1234 menu->addAction(menuAction);
1236 connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
1239 /** Lets the control know about the Options Model (and its signals) */
1240 void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel)
1242 if (_optionsModel)
1244 this->optionsModel = _optionsModel;
1246 // be aware of a display unit change reported by the OptionsModel object.
1247 connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
1249 // initialize the display units label with the current value in the model.
1250 updateDisplayUnit(_optionsModel->getDisplayUnit());
1254 /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
1255 void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits)
1257 setText(BitcoinUnits::name(newUnits));
1260 /** Shows context menu with Display Unit options by the mouse coordinates */
1261 void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint& point)
1263 QPoint globalPos = mapToGlobal(point);
1264 menu->exec(globalPos);
1267 /** Tells underlying optionsModel to update its current display unit. */
1268 void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
1270 if (action)
1272 optionsModel->setDisplayUnit(action->data());