Line data Source code
1 : // Copyright (c) 2011-2014 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 : #include "bitcoingui.h"
6 :
7 : #include "bitcoinunits.h"
8 : #include "clientmodel.h"
9 : #include "guiconstants.h"
10 : #include "guiutil.h"
11 : #include "networkstyle.h"
12 : #include "notificator.h"
13 : #include "openuridialog.h"
14 : #include "optionsdialog.h"
15 : #include "optionsmodel.h"
16 : #include "platformstyle.h"
17 : #include "rpcconsole.h"
18 : #include "utilitydialog.h"
19 :
20 : #ifdef ENABLE_WALLET
21 : #include "walletframe.h"
22 : #include "walletmodel.h"
23 : #endif // ENABLE_WALLET
24 :
25 : #ifdef Q_OS_MAC
26 : #include "macdockiconhandler.h"
27 : #endif
28 :
29 : #include "init.h"
30 : #include "ui_interface.h"
31 : #include "util.h"
32 :
33 : #include <iostream>
34 :
35 : #include <QAction>
36 : #include <QApplication>
37 : #include <QDateTime>
38 : #include <QDesktopWidget>
39 : #include <QDragEnterEvent>
40 : #include <QListWidget>
41 : #include <QMenuBar>
42 : #include <QMessageBox>
43 : #include <QMimeData>
44 : #include <QProgressBar>
45 : #include <QProgressDialog>
46 : #include <QSettings>
47 : #include <QStackedWidget>
48 : #include <QStatusBar>
49 : #include <QStyle>
50 : #include <QTimer>
51 : #include <QToolBar>
52 : #include <QVBoxLayout>
53 :
54 : #if QT_VERSION < 0x050000
55 : #include <QTextDocument>
56 : #include <QUrl>
57 : #else
58 : #include <QUrlQuery>
59 : #endif
60 :
61 0 : const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
62 :
63 0 : BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
64 : QMainWindow(parent),
65 : clientModel(0),
66 : walletFrame(0),
67 : unitDisplayControl(0),
68 : labelEncryptionIcon(0),
69 : labelConnectionsIcon(0),
70 : labelBlocksIcon(0),
71 : progressBarLabel(0),
72 : progressBar(0),
73 : progressDialog(0),
74 : appMenuBar(0),
75 : overviewAction(0),
76 : historyAction(0),
77 : quitAction(0),
78 : sendCoinsAction(0),
79 : sendCoinsMenuAction(0),
80 : usedSendingAddressesAction(0),
81 : usedReceivingAddressesAction(0),
82 : signMessageAction(0),
83 : verifyMessageAction(0),
84 : aboutAction(0),
85 : receiveCoinsAction(0),
86 : receiveCoinsMenuAction(0),
87 : optionsAction(0),
88 : toggleHideAction(0),
89 : encryptWalletAction(0),
90 : backupWalletAction(0),
91 : changePassphraseAction(0),
92 : aboutQtAction(0),
93 : openRPCConsoleAction(0),
94 : openAction(0),
95 : showHelpMessageAction(0),
96 : trayIcon(0),
97 : trayIconMenu(0),
98 : notificator(0),
99 : rpcConsole(0),
100 : helpMessageDialog(0),
101 : prevBlocks(0),
102 : spinnerFrame(0),
103 0 : platformStyle(platformStyle)
104 : {
105 0 : GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
106 :
107 0 : QString windowTitle = tr("Bitcoin Core") + " - ";
108 : #ifdef ENABLE_WALLET
109 : /* if compiled with wallet support, -disablewallet can still disable the wallet */
110 0 : enableWallet = !GetBoolArg("-disablewallet", false);
111 : #else
112 : enableWallet = false;
113 : #endif // ENABLE_WALLET
114 0 : if(enableWallet)
115 : {
116 0 : windowTitle += tr("Wallet");
117 : } else {
118 0 : windowTitle += tr("Node");
119 : }
120 0 : windowTitle += " " + networkStyle->getTitleAddText();
121 : #ifndef Q_OS_MAC
122 0 : QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
123 0 : setWindowIcon(networkStyle->getTrayAndWindowIcon());
124 : #else
125 : MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
126 : #endif
127 0 : setWindowTitle(windowTitle);
128 :
129 : #if defined(Q_OS_MAC) && QT_VERSION < 0x050000
130 : // This property is not implemented in Qt 5. Setting it has no effect.
131 : // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
132 : setUnifiedTitleAndToolBarOnMac(true);
133 : #endif
134 :
135 0 : rpcConsole = new RPCConsole(platformStyle, 0);
136 0 : helpMessageDialog = new HelpMessageDialog(this, false);
137 : #ifdef ENABLE_WALLET
138 0 : if(enableWallet)
139 : {
140 : /** Create wallet frame and make it the central widget */
141 0 : walletFrame = new WalletFrame(platformStyle, this);
142 0 : setCentralWidget(walletFrame);
143 : } else
144 : #endif // ENABLE_WALLET
145 : {
146 : /* When compiled without wallet or -disablewallet is provided,
147 : * the central widget is the rpc console.
148 : */
149 0 : setCentralWidget(rpcConsole);
150 : }
151 :
152 : // Accept D&D of URIs
153 0 : setAcceptDrops(true);
154 :
155 : // Create actions for the toolbar, menu bar and tray/dock icon
156 : // Needs walletFrame to be initialized
157 0 : createActions();
158 :
159 : // Create application menu bar
160 0 : createMenuBar();
161 :
162 : // Create the toolbars
163 0 : createToolBars();
164 :
165 : // Create system tray icon and notification
166 0 : createTrayIcon(networkStyle);
167 :
168 : // Create status bar
169 0 : statusBar();
170 :
171 : // Disable size grip because it looks ugly and nobody needs it
172 0 : statusBar()->setSizeGripEnabled(false);
173 :
174 : // Status bar notification icons
175 0 : QFrame *frameBlocks = new QFrame();
176 0 : frameBlocks->setContentsMargins(0,0,0,0);
177 0 : frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
178 0 : QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
179 0 : frameBlocksLayout->setContentsMargins(3,0,3,0);
180 0 : frameBlocksLayout->setSpacing(3);
181 0 : unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
182 0 : labelEncryptionIcon = new QLabel();
183 0 : labelConnectionsIcon = new QLabel();
184 0 : labelBlocksIcon = new QLabel();
185 0 : if(enableWallet)
186 : {
187 0 : frameBlocksLayout->addStretch();
188 0 : frameBlocksLayout->addWidget(unitDisplayControl);
189 0 : frameBlocksLayout->addStretch();
190 0 : frameBlocksLayout->addWidget(labelEncryptionIcon);
191 : }
192 0 : frameBlocksLayout->addStretch();
193 0 : frameBlocksLayout->addWidget(labelConnectionsIcon);
194 0 : frameBlocksLayout->addStretch();
195 0 : frameBlocksLayout->addWidget(labelBlocksIcon);
196 0 : frameBlocksLayout->addStretch();
197 :
198 : // Progress bar and label for blocks download
199 0 : progressBarLabel = new QLabel();
200 0 : progressBarLabel->setVisible(false);
201 0 : progressBar = new GUIUtil::ProgressBar();
202 0 : progressBar->setAlignment(Qt::AlignCenter);
203 0 : progressBar->setVisible(false);
204 :
205 : // Override style sheet for progress bar for styles that have a segmented progress bar,
206 : // as they make the text unreadable (workaround for issue #1071)
207 : // See https://qt-project.org/doc/qt-4.8/gallery.html
208 0 : QString curStyle = QApplication::style()->metaObject()->className();
209 0 : if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
210 : {
211 0 : 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; }");
212 : }
213 :
214 0 : statusBar()->addWidget(progressBarLabel);
215 0 : statusBar()->addWidget(progressBar);
216 0 : statusBar()->addPermanentWidget(frameBlocks);
217 :
218 : // Install event filter to be able to catch status tip events (QEvent::StatusTip)
219 0 : this->installEventFilter(this);
220 :
221 : // Initially wallet actions should be disabled
222 0 : setWalletActionsEnabled(false);
223 :
224 : // Subscribe to notifications from core
225 0 : subscribeToCoreSignals();
226 0 : }
227 :
228 0 : BitcoinGUI::~BitcoinGUI()
229 : {
230 : // Unsubscribe from notifications from core
231 : unsubscribeFromCoreSignals();
232 :
233 0 : GUIUtil::saveWindowGeometry("nWindow", this);
234 0 : if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
235 0 : trayIcon->hide();
236 : #ifdef Q_OS_MAC
237 : delete appMenuBar;
238 : MacDockIconHandler::cleanup();
239 : #endif
240 :
241 0 : delete rpcConsole;
242 0 : }
243 :
244 0 : void BitcoinGUI::createActions()
245 : {
246 0 : QActionGroup *tabGroup = new QActionGroup(this);
247 :
248 0 : overviewAction = new QAction(platformStyle->SingleColorIcon(":/icons/overview"), tr("&Overview"), this);
249 0 : overviewAction->setStatusTip(tr("Show general overview of wallet"));
250 0 : overviewAction->setToolTip(overviewAction->statusTip());
251 0 : overviewAction->setCheckable(true);
252 0 : overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
253 0 : tabGroup->addAction(overviewAction);
254 :
255 0 : sendCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/send"), tr("&Send"), this);
256 0 : sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
257 0 : sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
258 0 : sendCoinsAction->setCheckable(true);
259 0 : sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
260 0 : tabGroup->addAction(sendCoinsAction);
261 :
262 0 : sendCoinsMenuAction = new QAction(platformStyle->TextColorIcon(":/icons/send"), sendCoinsAction->text(), this);
263 0 : sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
264 0 : sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
265 :
266 0 : receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
267 0 : receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
268 0 : receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
269 0 : receiveCoinsAction->setCheckable(true);
270 0 : receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
271 0 : tabGroup->addAction(receiveCoinsAction);
272 :
273 0 : receiveCoinsMenuAction = new QAction(platformStyle->TextColorIcon(":/icons/receiving_addresses"), receiveCoinsAction->text(), this);
274 0 : receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
275 0 : receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
276 :
277 0 : historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
278 0 : historyAction->setStatusTip(tr("Browse transaction history"));
279 0 : historyAction->setToolTip(historyAction->statusTip());
280 0 : historyAction->setCheckable(true);
281 0 : historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
282 0 : tabGroup->addAction(historyAction);
283 :
284 : #ifdef ENABLE_WALLET
285 : // These showNormalIfMinimized are needed because Send Coins and Receive Coins
286 : // can be triggered from the tray menu, and need to show the GUI to be useful.
287 0 : connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
288 0 : connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
289 0 : connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
290 0 : connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
291 0 : connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
292 0 : connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
293 0 : connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
294 0 : connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
295 0 : connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
296 0 : connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
297 0 : connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
298 0 : connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
299 : #endif // ENABLE_WALLET
300 :
301 0 : quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this);
302 0 : quitAction->setStatusTip(tr("Quit application"));
303 0 : quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
304 0 : quitAction->setMenuRole(QAction::QuitRole);
305 0 : aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&About Bitcoin Core"), this);
306 0 : aboutAction->setStatusTip(tr("Show information about Bitcoin Core"));
307 0 : aboutAction->setMenuRole(QAction::AboutRole);
308 0 : aboutQtAction = new QAction(platformStyle->TextColorIcon(":/icons/about_qt"), tr("About &Qt"), this);
309 0 : aboutQtAction->setStatusTip(tr("Show information about Qt"));
310 0 : aboutQtAction->setMenuRole(QAction::AboutQtRole);
311 0 : optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"), tr("&Options..."), this);
312 0 : optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin Core"));
313 0 : optionsAction->setMenuRole(QAction::PreferencesRole);
314 0 : toggleHideAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&Show / Hide"), this);
315 0 : toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
316 :
317 0 : encryptWalletAction = new QAction(platformStyle->TextColorIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
318 0 : encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
319 0 : encryptWalletAction->setCheckable(true);
320 0 : backupWalletAction = new QAction(platformStyle->TextColorIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
321 0 : backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
322 0 : changePassphraseAction = new QAction(platformStyle->TextColorIcon(":/icons/key"), tr("&Change Passphrase..."), this);
323 0 : changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
324 0 : signMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/edit"), tr("Sign &message..."), this);
325 0 : signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
326 0 : verifyMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/verify"), tr("&Verify message..."), this);
327 0 : verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
328 :
329 0 : openRPCConsoleAction = new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"), tr("&Debug window"), this);
330 0 : openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
331 :
332 0 : usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
333 0 : usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
334 0 : usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
335 0 : usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
336 :
337 0 : openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
338 0 : openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
339 :
340 0 : showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
341 0 : showHelpMessageAction->setMenuRole(QAction::NoRole);
342 0 : showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options"));
343 :
344 0 : connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
345 0 : connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
346 0 : connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
347 0 : connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
348 0 : connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
349 0 : connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
350 0 : connect(openRPCConsoleAction, SIGNAL(triggered()), this, SLOT(showDebugWindow()));
351 : // prevents an open debug window from becoming stuck/unusable on client shutdown
352 0 : connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
353 :
354 : #ifdef ENABLE_WALLET
355 0 : if(walletFrame)
356 : {
357 0 : connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
358 0 : connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
359 0 : connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
360 0 : connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
361 0 : connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
362 0 : connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
363 0 : connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
364 0 : connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
365 : }
366 : #endif // ENABLE_WALLET
367 0 : }
368 :
369 0 : void BitcoinGUI::createMenuBar()
370 : {
371 : #ifdef Q_OS_MAC
372 : // Create a decoupled menu bar on Mac which stays even if the window is closed
373 : appMenuBar = new QMenuBar();
374 : #else
375 : // Get the main window's menu bar on other platforms
376 0 : appMenuBar = menuBar();
377 : #endif
378 :
379 : // Configure the menus
380 0 : QMenu *file = appMenuBar->addMenu(tr("&File"));
381 0 : if(walletFrame)
382 : {
383 0 : file->addAction(openAction);
384 0 : file->addAction(backupWalletAction);
385 0 : file->addAction(signMessageAction);
386 0 : file->addAction(verifyMessageAction);
387 0 : file->addSeparator();
388 0 : file->addAction(usedSendingAddressesAction);
389 0 : file->addAction(usedReceivingAddressesAction);
390 0 : file->addSeparator();
391 : }
392 0 : file->addAction(quitAction);
393 :
394 0 : QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
395 0 : if(walletFrame)
396 : {
397 0 : settings->addAction(encryptWalletAction);
398 0 : settings->addAction(changePassphraseAction);
399 0 : settings->addSeparator();
400 : }
401 0 : settings->addAction(optionsAction);
402 :
403 0 : QMenu *help = appMenuBar->addMenu(tr("&Help"));
404 0 : if(walletFrame)
405 : {
406 0 : help->addAction(openRPCConsoleAction);
407 : }
408 0 : help->addAction(showHelpMessageAction);
409 0 : help->addSeparator();
410 0 : help->addAction(aboutAction);
411 0 : help->addAction(aboutQtAction);
412 0 : }
413 :
414 0 : void BitcoinGUI::createToolBars()
415 : {
416 0 : if(walletFrame)
417 : {
418 0 : QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
419 0 : toolbar->setMovable(false);
420 0 : toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
421 0 : toolbar->addAction(overviewAction);
422 0 : toolbar->addAction(sendCoinsAction);
423 0 : toolbar->addAction(receiveCoinsAction);
424 0 : toolbar->addAction(historyAction);
425 0 : overviewAction->setChecked(true);
426 : }
427 0 : }
428 :
429 0 : void BitcoinGUI::setClientModel(ClientModel *clientModel)
430 : {
431 0 : this->clientModel = clientModel;
432 0 : if(clientModel)
433 : {
434 : // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
435 : // while the client has not yet fully loaded
436 0 : createTrayIconMenu();
437 :
438 : // Keep up to date with client
439 0 : setNumConnections(clientModel->getNumConnections());
440 0 : connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
441 :
442 0 : setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate());
443 0 : connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
444 :
445 : // Receive and report messages from client model
446 0 : connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
447 :
448 : // Show progress dialog
449 0 : connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
450 :
451 0 : rpcConsole->setClientModel(clientModel);
452 : #ifdef ENABLE_WALLET
453 0 : if(walletFrame)
454 : {
455 0 : walletFrame->setClientModel(clientModel);
456 : }
457 : #endif // ENABLE_WALLET
458 0 : unitDisplayControl->setOptionsModel(clientModel->getOptionsModel());
459 : } else {
460 : // Disable possibility to show main window via action
461 0 : toggleHideAction->setEnabled(false);
462 0 : if(trayIconMenu)
463 : {
464 : // Disable context menu on tray icon
465 0 : trayIconMenu->clear();
466 : }
467 : }
468 0 : }
469 :
470 : #ifdef ENABLE_WALLET
471 0 : bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
472 : {
473 0 : if(!walletFrame)
474 : return false;
475 0 : setWalletActionsEnabled(true);
476 0 : return walletFrame->addWallet(name, walletModel);
477 : }
478 :
479 0 : bool BitcoinGUI::setCurrentWallet(const QString& name)
480 : {
481 0 : if(!walletFrame)
482 : return false;
483 0 : return walletFrame->setCurrentWallet(name);
484 : }
485 :
486 0 : void BitcoinGUI::removeAllWallets()
487 : {
488 0 : if(!walletFrame)
489 0 : return;
490 0 : setWalletActionsEnabled(false);
491 0 : walletFrame->removeAllWallets();
492 : }
493 : #endif // ENABLE_WALLET
494 :
495 0 : void BitcoinGUI::setWalletActionsEnabled(bool enabled)
496 : {
497 0 : overviewAction->setEnabled(enabled);
498 0 : sendCoinsAction->setEnabled(enabled);
499 0 : sendCoinsMenuAction->setEnabled(enabled);
500 0 : receiveCoinsAction->setEnabled(enabled);
501 0 : receiveCoinsMenuAction->setEnabled(enabled);
502 0 : historyAction->setEnabled(enabled);
503 0 : encryptWalletAction->setEnabled(enabled);
504 0 : backupWalletAction->setEnabled(enabled);
505 0 : changePassphraseAction->setEnabled(enabled);
506 0 : signMessageAction->setEnabled(enabled);
507 0 : verifyMessageAction->setEnabled(enabled);
508 0 : usedSendingAddressesAction->setEnabled(enabled);
509 0 : usedReceivingAddressesAction->setEnabled(enabled);
510 0 : openAction->setEnabled(enabled);
511 0 : }
512 :
513 0 : void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
514 : {
515 : #ifndef Q_OS_MAC
516 0 : trayIcon = new QSystemTrayIcon(this);
517 0 : QString toolTip = tr("Bitcoin Core client") + " " + networkStyle->getTitleAddText();
518 0 : trayIcon->setToolTip(toolTip);
519 0 : trayIcon->setIcon(networkStyle->getTrayAndWindowIcon());
520 0 : trayIcon->show();
521 : #endif
522 :
523 0 : notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
524 0 : }
525 :
526 0 : void BitcoinGUI::createTrayIconMenu()
527 : {
528 : #ifndef Q_OS_MAC
529 : // return if trayIcon is unset (only on non-Mac OSes)
530 0 : if (!trayIcon)
531 0 : return;
532 :
533 0 : trayIconMenu = new QMenu(this);
534 0 : trayIcon->setContextMenu(trayIconMenu);
535 :
536 : connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
537 0 : this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
538 : #else
539 : // Note: On Mac, the dock icon is used to provide the tray's functionality.
540 : MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
541 : dockIconHandler->setMainWindow((QMainWindow *)this);
542 : trayIconMenu = dockIconHandler->dockMenu();
543 : #endif
544 :
545 : // Configuration of the tray icon (or dock icon) icon menu
546 0 : trayIconMenu->addAction(toggleHideAction);
547 0 : trayIconMenu->addSeparator();
548 0 : trayIconMenu->addAction(sendCoinsMenuAction);
549 0 : trayIconMenu->addAction(receiveCoinsMenuAction);
550 0 : trayIconMenu->addSeparator();
551 0 : trayIconMenu->addAction(signMessageAction);
552 0 : trayIconMenu->addAction(verifyMessageAction);
553 0 : trayIconMenu->addSeparator();
554 0 : trayIconMenu->addAction(optionsAction);
555 0 : trayIconMenu->addAction(openRPCConsoleAction);
556 : #ifndef Q_OS_MAC // This is built-in on Mac
557 0 : trayIconMenu->addSeparator();
558 0 : trayIconMenu->addAction(quitAction);
559 : #endif
560 : }
561 :
562 : #ifndef Q_OS_MAC
563 0 : void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
564 : {
565 0 : if(reason == QSystemTrayIcon::Trigger)
566 : {
567 : // Click on system tray icon triggers show/hide of the main window
568 : toggleHidden();
569 : }
570 0 : }
571 : #endif
572 :
573 0 : void BitcoinGUI::optionsClicked()
574 : {
575 0 : if(!clientModel || !clientModel->getOptionsModel())
576 0 : return;
577 :
578 0 : OptionsDialog dlg(this, enableWallet);
579 0 : dlg.setModel(clientModel->getOptionsModel());
580 0 : dlg.exec();
581 : }
582 :
583 0 : void BitcoinGUI::aboutClicked()
584 : {
585 0 : if(!clientModel)
586 0 : return;
587 :
588 0 : HelpMessageDialog dlg(this, true);
589 0 : dlg.exec();
590 : }
591 :
592 0 : void BitcoinGUI::showDebugWindow()
593 : {
594 0 : rpcConsole->showNormal();
595 0 : rpcConsole->show();
596 0 : rpcConsole->raise();
597 0 : rpcConsole->activateWindow();
598 0 : }
599 :
600 0 : void BitcoinGUI::showHelpMessageClicked()
601 : {
602 0 : helpMessageDialog->show();
603 0 : }
604 :
605 : #ifdef ENABLE_WALLET
606 0 : void BitcoinGUI::openClicked()
607 : {
608 0 : OpenURIDialog dlg(this);
609 0 : if(dlg.exec())
610 : {
611 0 : Q_EMIT receivedURI(dlg.getURI());
612 0 : }
613 0 : }
614 :
615 0 : void BitcoinGUI::gotoOverviewPage()
616 : {
617 0 : overviewAction->setChecked(true);
618 0 : if (walletFrame) walletFrame->gotoOverviewPage();
619 0 : }
620 :
621 0 : void BitcoinGUI::gotoHistoryPage()
622 : {
623 0 : historyAction->setChecked(true);
624 0 : if (walletFrame) walletFrame->gotoHistoryPage();
625 0 : }
626 :
627 0 : void BitcoinGUI::gotoReceiveCoinsPage()
628 : {
629 0 : receiveCoinsAction->setChecked(true);
630 0 : if (walletFrame) walletFrame->gotoReceiveCoinsPage();
631 0 : }
632 :
633 0 : void BitcoinGUI::gotoSendCoinsPage(QString addr)
634 : {
635 0 : sendCoinsAction->setChecked(true);
636 0 : if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
637 0 : }
638 :
639 0 : void BitcoinGUI::gotoSignMessageTab(QString addr)
640 : {
641 0 : if (walletFrame) walletFrame->gotoSignMessageTab(addr);
642 0 : }
643 :
644 0 : void BitcoinGUI::gotoVerifyMessageTab(QString addr)
645 : {
646 0 : if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
647 0 : }
648 : #endif // ENABLE_WALLET
649 :
650 0 : void BitcoinGUI::setNumConnections(int count)
651 : {
652 : QString icon;
653 0 : switch(count)
654 : {
655 0 : case 0: icon = ":/icons/connect_0"; break;
656 0 : case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
657 0 : case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
658 0 : case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
659 0 : default: icon = ":/icons/connect_4"; break;
660 : }
661 0 : labelConnectionsIcon->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
662 0 : labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
663 0 : }
664 :
665 0 : void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
666 : {
667 0 : if(!clientModel)
668 0 : return;
669 :
670 : // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text)
671 0 : statusBar()->clearMessage();
672 :
673 : // Acquire current block source
674 0 : enum BlockSource blockSource = clientModel->getBlockSource();
675 0 : switch (blockSource) {
676 : case BLOCK_SOURCE_NETWORK:
677 0 : progressBarLabel->setText(tr("Synchronizing with network..."));
678 0 : break;
679 : case BLOCK_SOURCE_DISK:
680 0 : progressBarLabel->setText(tr("Importing blocks from disk..."));
681 0 : break;
682 : case BLOCK_SOURCE_REINDEX:
683 0 : progressBarLabel->setText(tr("Reindexing blocks on disk..."));
684 0 : break;
685 : case BLOCK_SOURCE_NONE:
686 : // Case: not Importing, not Reindexing and no network connection
687 0 : progressBarLabel->setText(tr("No block source available..."));
688 0 : break;
689 : }
690 :
691 : QString tooltip;
692 :
693 0 : QDateTime currentDate = QDateTime::currentDateTime();
694 0 : qint64 secs = blockDate.secsTo(currentDate);
695 :
696 0 : tooltip = tr("Processed %n block(s) of transaction history.", "", count);
697 :
698 : // Set icon state: spinning if catching up, tick otherwise
699 0 : if(secs < 90*60)
700 : {
701 0 : tooltip = tr("Up to date") + QString(".<br>") + tooltip;
702 0 : labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
703 :
704 : #ifdef ENABLE_WALLET
705 0 : if(walletFrame)
706 0 : walletFrame->showOutOfSyncWarning(false);
707 : #endif // ENABLE_WALLET
708 :
709 0 : progressBarLabel->setVisible(false);
710 0 : progressBar->setVisible(false);
711 : }
712 : else
713 : {
714 : // Represent time from last generated block in human readable text
715 : QString timeBehindText;
716 0 : const int HOUR_IN_SECONDS = 60*60;
717 0 : const int DAY_IN_SECONDS = 24*60*60;
718 0 : const int WEEK_IN_SECONDS = 7*24*60*60;
719 0 : const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
720 0 : if(secs < 2*DAY_IN_SECONDS)
721 : {
722 0 : timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS);
723 : }
724 0 : else if(secs < 2*WEEK_IN_SECONDS)
725 : {
726 0 : timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS);
727 : }
728 0 : else if(secs < YEAR_IN_SECONDS)
729 : {
730 0 : timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS);
731 : }
732 : else
733 : {
734 0 : qint64 years = secs / YEAR_IN_SECONDS;
735 0 : qint64 remainder = secs % YEAR_IN_SECONDS;
736 0 : timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS));
737 : }
738 :
739 0 : progressBarLabel->setVisible(true);
740 0 : progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
741 0 : progressBar->setMaximum(1000000000);
742 0 : progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
743 0 : progressBar->setVisible(true);
744 :
745 0 : tooltip = tr("Catching up...") + QString("<br>") + tooltip;
746 0 : if(count != prevBlocks)
747 : {
748 : labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(QString(
749 : ":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')))
750 0 : .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
751 0 : spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
752 : }
753 0 : prevBlocks = count;
754 :
755 : #ifdef ENABLE_WALLET
756 0 : if(walletFrame)
757 0 : walletFrame->showOutOfSyncWarning(true);
758 : #endif // ENABLE_WALLET
759 :
760 0 : tooltip += QString("<br>");
761 0 : tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
762 0 : tooltip += QString("<br>");
763 0 : tooltip += tr("Transactions after this will not yet be visible.");
764 : }
765 :
766 : // Don't word-wrap this (fixed-width) tooltip
767 0 : tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
768 :
769 0 : labelBlocksIcon->setToolTip(tooltip);
770 0 : progressBarLabel->setToolTip(tooltip);
771 0 : progressBar->setToolTip(tooltip);
772 : }
773 :
774 0 : void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
775 : {
776 : QString strTitle = tr("Bitcoin"); // default title
777 : // Default to information icon
778 0 : int nMBoxIcon = QMessageBox::Information;
779 0 : int nNotifyIcon = Notificator::Information;
780 :
781 0 : QString msgType;
782 :
783 : // Prefer supplied title over style based title
784 0 : if (!title.isEmpty()) {
785 0 : msgType = title;
786 : }
787 : else {
788 0 : switch (style) {
789 : case CClientUIInterface::MSG_ERROR:
790 0 : msgType = tr("Error");
791 0 : break;
792 : case CClientUIInterface::MSG_WARNING:
793 0 : msgType = tr("Warning");
794 0 : break;
795 : case CClientUIInterface::MSG_INFORMATION:
796 0 : msgType = tr("Information");
797 0 : break;
798 : default:
799 : break;
800 : }
801 : }
802 : // Append title to "Bitcoin - "
803 0 : if (!msgType.isEmpty())
804 0 : strTitle += " - " + msgType;
805 :
806 : // Check for error/warning icon
807 0 : if (style & CClientUIInterface::ICON_ERROR) {
808 : nMBoxIcon = QMessageBox::Critical;
809 : nNotifyIcon = Notificator::Critical;
810 : }
811 0 : else if (style & CClientUIInterface::ICON_WARNING) {
812 0 : nMBoxIcon = QMessageBox::Warning;
813 0 : nNotifyIcon = Notificator::Warning;
814 : }
815 :
816 : // Display message
817 0 : if (style & CClientUIInterface::MODAL) {
818 : // Check for buttons, use OK as default, if none was supplied
819 : QMessageBox::StandardButton buttons;
820 0 : if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
821 0 : buttons = QMessageBox::Ok;
822 :
823 0 : showNormalIfMinimized();
824 0 : QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
825 0 : int r = mBox.exec();
826 0 : if (ret != NULL)
827 0 : *ret = r == QMessageBox::Ok;
828 : }
829 : else
830 0 : notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
831 0 : }
832 :
833 0 : void BitcoinGUI::changeEvent(QEvent *e)
834 : {
835 0 : QMainWindow::changeEvent(e);
836 : #ifndef Q_OS_MAC // Ignored on Mac
837 0 : if(e->type() == QEvent::WindowStateChange)
838 : {
839 0 : if(clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getMinimizeToTray())
840 : {
841 0 : QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
842 0 : if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
843 : {
844 0 : QTimer::singleShot(0, this, SLOT(hide()));
845 : e->ignore();
846 : }
847 : }
848 : }
849 : #endif
850 0 : }
851 :
852 0 : void BitcoinGUI::closeEvent(QCloseEvent *event)
853 : {
854 : #ifndef Q_OS_MAC // Ignored on Mac
855 0 : if(clientModel && clientModel->getOptionsModel())
856 : {
857 0 : if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
858 0 : !clientModel->getOptionsModel()->getMinimizeOnClose())
859 : {
860 : // close rpcConsole in case it was open to make some space for the shutdown window
861 0 : rpcConsole->close();
862 :
863 0 : QApplication::quit();
864 : }
865 : }
866 : #endif
867 0 : QMainWindow::closeEvent(event);
868 0 : }
869 :
870 : #ifdef ENABLE_WALLET
871 0 : void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
872 : {
873 : // On new transaction, make an info balloon
874 0 : QString msg = tr("Date: %1\n").arg(date) +
875 : tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) +
876 0 : tr("Type: %1\n").arg(type);
877 0 : if (!label.isEmpty())
878 0 : msg += tr("Label: %1\n").arg(label);
879 0 : else if (!address.isEmpty())
880 0 : msg += tr("Address: %1\n").arg(address);
881 0 : message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
882 0 : msg, CClientUIInterface::MSG_INFORMATION);
883 0 : }
884 : #endif // ENABLE_WALLET
885 :
886 0 : void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
887 : {
888 : // Accept only URIs
889 0 : if(event->mimeData()->hasUrls())
890 0 : event->acceptProposedAction();
891 0 : }
892 :
893 0 : void BitcoinGUI::dropEvent(QDropEvent *event)
894 : {
895 0 : if(event->mimeData()->hasUrls())
896 : {
897 0 : Q_FOREACH(const QUrl &uri, event->mimeData()->urls())
898 : {
899 0 : Q_EMIT receivedURI(uri.toString());
900 : }
901 : }
902 : event->acceptProposedAction();
903 0 : }
904 :
905 0 : bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
906 : {
907 : // Catch status tip events
908 0 : if (event->type() == QEvent::StatusTip)
909 : {
910 : // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
911 0 : if (progressBarLabel->isVisible() || progressBar->isVisible())
912 : return true;
913 : }
914 0 : return QMainWindow::eventFilter(object, event);
915 : }
916 :
917 : #ifdef ENABLE_WALLET
918 0 : bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
919 : {
920 : // URI has to be valid
921 0 : if (walletFrame && walletFrame->handlePaymentRequest(recipient))
922 : {
923 0 : showNormalIfMinimized();
924 0 : gotoSendCoinsPage();
925 0 : return true;
926 : }
927 : return false;
928 : }
929 :
930 0 : void BitcoinGUI::setEncryptionStatus(int status)
931 : {
932 0 : switch(status)
933 : {
934 : case WalletModel::Unencrypted:
935 0 : labelEncryptionIcon->hide();
936 0 : encryptWalletAction->setChecked(false);
937 0 : changePassphraseAction->setEnabled(false);
938 0 : encryptWalletAction->setEnabled(true);
939 0 : break;
940 : case WalletModel::Unlocked:
941 0 : labelEncryptionIcon->show();
942 0 : labelEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
943 0 : labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
944 0 : encryptWalletAction->setChecked(true);
945 0 : changePassphraseAction->setEnabled(true);
946 0 : encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
947 0 : break;
948 : case WalletModel::Locked:
949 0 : labelEncryptionIcon->show();
950 0 : labelEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
951 0 : labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
952 0 : encryptWalletAction->setChecked(true);
953 0 : changePassphraseAction->setEnabled(true);
954 0 : encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
955 0 : break;
956 : }
957 0 : }
958 : #endif // ENABLE_WALLET
959 :
960 0 : void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
961 : {
962 0 : if(!clientModel)
963 0 : return;
964 :
965 : // activateWindow() (sometimes) helps with keyboard focus on Windows
966 0 : if (isHidden())
967 : {
968 0 : show();
969 0 : activateWindow();
970 : }
971 0 : else if (isMinimized())
972 : {
973 0 : showNormal();
974 0 : activateWindow();
975 : }
976 0 : else if (GUIUtil::isObscured(this))
977 : {
978 0 : raise();
979 0 : activateWindow();
980 : }
981 0 : else if(fToggleHidden)
982 0 : hide();
983 : }
984 :
985 0 : void BitcoinGUI::toggleHidden()
986 : {
987 0 : showNormalIfMinimized(true);
988 0 : }
989 :
990 0 : void BitcoinGUI::detectShutdown()
991 : {
992 0 : if (ShutdownRequested())
993 : {
994 0 : if(rpcConsole)
995 0 : rpcConsole->hide();
996 0 : qApp->quit();
997 : }
998 0 : }
999 :
1000 0 : void BitcoinGUI::showProgress(const QString &title, int nProgress)
1001 : {
1002 0 : if (nProgress == 0)
1003 : {
1004 0 : progressDialog = new QProgressDialog(title, "", 0, 100);
1005 0 : progressDialog->setWindowModality(Qt::ApplicationModal);
1006 0 : progressDialog->setMinimumDuration(0);
1007 0 : progressDialog->setCancelButton(0);
1008 0 : progressDialog->setAutoClose(false);
1009 0 : progressDialog->setValue(0);
1010 : }
1011 0 : else if (nProgress == 100)
1012 : {
1013 0 : if (progressDialog)
1014 : {
1015 0 : progressDialog->close();
1016 0 : progressDialog->deleteLater();
1017 : }
1018 : }
1019 0 : else if (progressDialog)
1020 0 : progressDialog->setValue(nProgress);
1021 0 : }
1022 :
1023 0 : static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
1024 : {
1025 0 : bool modal = (style & CClientUIInterface::MODAL);
1026 : // The SECURE flag has no effect in the Qt GUI.
1027 : // bool secure = (style & CClientUIInterface::SECURE);
1028 0 : style &= ~CClientUIInterface::SECURE;
1029 0 : bool ret = false;
1030 : // In case of modal message, use blocking connection to wait for user to click a button
1031 : QMetaObject::invokeMethod(gui, "message",
1032 : modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1033 : Q_ARG(QString, QString::fromStdString(caption)),
1034 : Q_ARG(QString, QString::fromStdString(message)),
1035 : Q_ARG(unsigned int, style),
1036 0 : Q_ARG(bool*, &ret));
1037 0 : return ret;
1038 : }
1039 :
1040 0 : void BitcoinGUI::subscribeToCoreSignals()
1041 : {
1042 : // Connect signals to client
1043 0 : uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
1044 0 : }
1045 :
1046 0 : void BitcoinGUI::unsubscribeFromCoreSignals()
1047 : {
1048 : // Disconnect signals from client
1049 0 : uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
1050 0 : }
1051 :
1052 0 : UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
1053 : optionsModel(0),
1054 0 : menu(0)
1055 : {
1056 0 : createContextMenu();
1057 0 : setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1058 0 : QList<BitcoinUnits::Unit> units = BitcoinUnits::availableUnits();
1059 0 : int max_width = 0;
1060 0 : const QFontMetrics fm(font());
1061 0 : Q_FOREACH (const BitcoinUnits::Unit unit, units)
1062 : {
1063 0 : max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit)));
1064 : }
1065 0 : setMinimumSize(max_width, 0);
1066 0 : setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1067 0 : setStyleSheet(QString("QLabel { color : %1 }").arg(platformStyle->SingleColor().name()));
1068 0 : }
1069 :
1070 : /** So that it responds to button clicks */
1071 0 : void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
1072 : {
1073 0 : onDisplayUnitsClicked(event->pos());
1074 0 : }
1075 :
1076 : /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
1077 0 : void UnitDisplayStatusBarControl::createContextMenu()
1078 : {
1079 0 : menu = new QMenu();
1080 0 : Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
1081 : {
1082 0 : QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
1083 0 : menuAction->setData(QVariant(u));
1084 0 : menu->addAction(menuAction);
1085 : }
1086 0 : connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
1087 0 : }
1088 :
1089 : /** Lets the control know about the Options Model (and its signals) */
1090 0 : void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel)
1091 : {
1092 0 : if (optionsModel)
1093 : {
1094 0 : this->optionsModel = optionsModel;
1095 :
1096 : // be aware of a display unit change reported by the OptionsModel object.
1097 0 : connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
1098 :
1099 : // initialize the display units label with the current value in the model.
1100 0 : updateDisplayUnit(optionsModel->getDisplayUnit());
1101 : }
1102 0 : }
1103 :
1104 : /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
1105 0 : void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits)
1106 : {
1107 0 : setText(BitcoinUnits::name(newUnits));
1108 0 : }
1109 :
1110 : /** Shows context menu with Display Unit options by the mouse coordinates */
1111 0 : void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint& point)
1112 : {
1113 0 : QPoint globalPos = mapToGlobal(point);
1114 0 : menu->exec(globalPos);
1115 0 : }
1116 :
1117 : /** Tells underlying optionsModel to update its current display unit. */
1118 0 : void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
1119 : {
1120 0 : if (action)
1121 : {
1122 0 : optionsModel->setDisplayUnit(action->data());
1123 : }
1124 0 : }
|