]> Git Repo - VerusCoin.git/blame - src/qt/bitcoingui.cpp
qt: Show weeks as well as years behind for long timespans
[VerusCoin.git] / src / qt / bitcoingui.cpp
CommitLineData
57702541 1// Copyright (c) 2011-2014 The Bitcoin developers
e592d43f
WL
2// Distributed under the MIT/X11 software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
32af5266 4
0fd01780 5#include "bitcoingui.h"
32af5266 6
e285ffcd 7#include "bitcoinunits.h"
51ed9ec9 8#include "clientmodel.h"
ae8adeb9 9#include "guiconstants.h"
86d56349 10#include "guiutil.h"
51ed9ec9 11#include "notificator.h"
309f796b 12#include "openuridialog.h"
51ed9ec9
BD
13#include "optionsdialog.h"
14#include "optionsmodel.h"
460c51fd 15#include "rpcconsole.h"
7b50bb2f 16#include "utilitydialog.h"
b7f4b6d3 17#ifdef ENABLE_WALLET
51ed9ec9
BD
18#include "walletframe.h"
19#include "walletmodel.h"
b7f4b6d3 20#endif
aaa1c3c4 21
81605d90 22#ifdef Q_OS_MAC
527137e3 23#include "macdockiconhandler.h"
24#endif
25
51ed9ec9
BD
26#include "init.h"
27#include "ui_interface.h"
28
29#include <iostream>
30
84ef729a 31#include <QApplication>
51ed9ec9
BD
32#include <QDateTime>
33#include <QDesktopWidget>
34#include <QDragEnterEvent>
aaa1c3c4 35#include <QIcon>
aaa1c3c4 36#include <QLabel>
51ed9ec9
BD
37#include <QListWidget>
38#include <QMenu>
39#include <QMenuBar>
6630c1cb 40#include <QMessageBox>
51ed9ec9 41#include <QMimeData>
6cab6635 42#include <QProgressBar>
51ed9ec9 43#include <QSettings>
64c8b699 44#include <QStackedWidget>
51ed9ec9
BD
45#include <QStatusBar>
46#include <QStyle>
08ed96d8 47#include <QTimer>
51ed9ec9
BD
48#include <QToolBar>
49#include <QVBoxLayout>
50
25c0cce7 51#if QT_VERSION < 0x050000
db7f0234 52#include <QUrl>
a41d5fe0 53#include <QTextDocument>
51ed9ec9
BD
54#else
55#include <QUrlQuery>
25c0cce7 56#endif
aaa1c3c4 57
67155d92
EL
58const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
59
80fccb0e 60BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
ef079e18
WL
61 QMainWindow(parent),
62 clientModel(0),
b7f4b6d3 63 walletFrame(0),
b7bcaf94
WL
64 encryptWalletAction(0),
65 changePassphraseAction(0),
01ea41b2 66 aboutQtAction(0),
cf9195c8 67 trayIcon(0),
460c51fd 68 notificator(0),
24cde0b7 69 rpcConsole(0),
f10b2d70
WL
70 prevBlocks(0),
71 spinnerFrame(0)
aaa1c3c4 72{
c431e9f1 73 GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
80fccb0e 74
b7f4b6d3
WL
75 QString windowTitle = tr("Bitcoin Core") + " - ";
76#ifdef ENABLE_WALLET
77 /* if compiled with wallet support, -disablewallet can still disable the wallet */
78 bool enableWallet = !GetBoolArg("-disablewallet", false);
79#else
80 bool enableWallet = false;
81#endif
82 if(enableWallet)
83 {
84 windowTitle += tr("Wallet");
85 } else {
86 windowTitle += tr("Node");
87 }
88
80fccb0e
PK
89 if (!fIsTestnet)
90 {
84f8551f 91#ifndef Q_OS_MAC
80fccb0e
PK
92 QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
93 setWindowIcon(QIcon(":icons/bitcoin"));
84f8551f
PK
94#else
95 MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin"));
96#endif
80fccb0e
PK
97 }
98 else
99 {
b7f4b6d3 100 windowTitle += " " + tr("[testnet]");
84f8551f 101#ifndef Q_OS_MAC
80fccb0e
PK
102 QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
103 setWindowIcon(QIcon(":icons/bitcoin_testnet"));
527137e3 104#else
80fccb0e 105 MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
527137e3 106#endif
84f8551f 107 }
b7f4b6d3 108 setWindowTitle(windowTitle);
84f8551f
PK
109
110#if defined(Q_OS_MAC) && QT_VERSION < 0x050000
111 // This property is not implemented in Qt 5. Setting it has no effect.
112 // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
113 setUnifiedTitleAndToolBarOnMac(true);
114#endif
80fccb0e 115
b7f4b6d3
WL
116 rpcConsole = new RPCConsole(enableWallet ? this : 0);
117#ifdef ENABLE_WALLET
118 if(enableWallet)
119 {
120 /** Create wallet frame and make it the central widget */
121 walletFrame = new WalletFrame(this);
122 setCentralWidget(walletFrame);
123 } else
124#endif
125 {
126 /* When compiled without wallet or -disablewallet is provided,
127 * the central widget is the rpc console.
128 */
129 setCentralWidget(rpcConsole);
130 }
7e600cd9 131
b0849613
WL
132 // Accept D&D of URIs
133 setAcceptDrops(true);
3f323a61 134
527137e3 135 // Create actions for the toolbar, menu bar and tray/dock icon
7e600cd9 136 // Needs walletFrame to be initialized
80fccb0e 137 createActions(fIsTestnet);
af943776 138
527137e3 139 // Create application menu bar
140 createMenuBar();
9958e09d 141
527137e3 142 // Create the toolbars
143 createToolBars();
aaa1c3c4 144
f8210212 145 // Create system tray icon and notification
80fccb0e 146 createTrayIcon(fIsTestnet);
64c8b699 147
352083cb 148 // Create status bar
3f323a61 149 statusBar();
b1ef1b24 150
b0849613 151 // Status bar notification icons
8dcffd4d 152 QFrame *frameBlocks = new QFrame();
2351a3fc 153 frameBlocks->setContentsMargins(0,0,0,0);
1bcf81e0 154 frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
8dcffd4d
WL
155 QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
156 frameBlocksLayout->setContentsMargins(3,0,3,0);
157 frameBlocksLayout->setSpacing(3);
ae8adeb9 158 labelEncryptionIcon = new QLabel();
2351a3fc 159 labelConnectionsIcon = new QLabel();
8dcffd4d 160 labelBlocksIcon = new QLabel();
2351a3fc 161 frameBlocksLayout->addStretch();
ae8adeb9
WL
162 frameBlocksLayout->addWidget(labelEncryptionIcon);
163 frameBlocksLayout->addStretch();
2351a3fc
WL
164 frameBlocksLayout->addWidget(labelConnectionsIcon);
165 frameBlocksLayout->addStretch();
8dcffd4d 166 frameBlocksLayout->addWidget(labelBlocksIcon);
8dcffd4d 167 frameBlocksLayout->addStretch();
5e1feddc 168
c7c0c931
PK
169 // Progress bar and label for blocks download
170 progressBarLabel = new QLabel();
6cab6635
WL
171 progressBarLabel->setVisible(false);
172 progressBar = new QProgressBar();
e72c6a18 173 progressBar->setAlignment(Qt::AlignCenter);
6cab6635
WL
174 progressBar->setVisible(false);
175
382b75f5
WL
176 // Override style sheet for progress bar for styles that have a segmented progress bar,
177 // as they make the text unreadable (workaround for issue #1071)
178 // See https://qt-project.org/doc/qt-4.8/gallery.html
1ce04488 179 QString curStyle = QApplication::style()->metaObject()->className();
382b75f5
WL
180 if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
181 {
182 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; }");
183 }
184
6cab6635
WL
185 statusBar()->addWidget(progressBarLabel);
186 statusBar()->addWidget(progressBar);
8dcffd4d 187 statusBar()->addPermanentWidget(frameBlocks);
6cab6635 188
460c51fd 189 connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
b7f4b6d3 190
a8d0c1e8
PK
191 // prevents an oben debug window from becoming stuck/unusable on client shutdown
192 connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
460c51fd 193
6f959c4c
PK
194 // Install event filter to be able to catch status tip events (QEvent::StatusTip)
195 this->installEventFilter(this);
146ba964
WL
196
197 // Initially wallet actions should be disabled
198 setWalletActionsEnabled(false);
35ecf854
WL
199
200 // Subscribe to notifications from core
201 subscribeToCoreSignals();
3f323a61
WL
202}
203
527137e3 204BitcoinGUI::~BitcoinGUI()
205{
35ecf854
WL
206 // Unsubscribe from notifications from core
207 unsubscribeFromCoreSignals();
208
c431e9f1 209 GUIUtil::saveWindowGeometry("nWindow", this);
27a0ed8a
WL
210 if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
211 trayIcon->hide();
81605d90 212#ifdef Q_OS_MAC
527137e3 213 delete appMenuBar;
4d17a1b0 214 MacDockIconHandler::instance()->setMainWindow(NULL);
527137e3 215#endif
216}
217
80fccb0e 218void BitcoinGUI::createActions(bool fIsTestnet)
3f323a61 219{
64c8b699 220 QActionGroup *tabGroup = new QActionGroup(this);
3479849d 221
64c8b699 222 overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
6f959c4c
PK
223 overviewAction->setStatusTip(tr("Show general overview of wallet"));
224 overviewAction->setToolTip(overviewAction->statusTip());
64c8b699 225 overviewAction->setCheckable(true);
d85f2458 226 overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
64c8b699 227 tabGroup->addAction(overviewAction);
3479849d 228
0de26d58 229 sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this);
6f959c4c
PK
230 sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
231 sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
382e9e25
PK
232 sendCoinsAction->setCheckable(true);
233 sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
234 tabGroup->addAction(sendCoinsAction);
235
0de26d58 236 receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
d57a496c 237 receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
6f959c4c 238 receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
382e9e25
PK
239 receiveCoinsAction->setCheckable(true);
240 receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
241 tabGroup->addAction(receiveCoinsAction);
242
d52a0f3b 243 historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
6f959c4c
PK
244 historyAction->setStatusTip(tr("Browse transaction history"));
245 historyAction->setToolTip(historyAction->statusTip());
64c8b699 246 historyAction->setCheckable(true);
d85f2458 247 historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
64c8b699
WL
248 tabGroup->addAction(historyAction);
249
d2b6de03
WL
250 // These showNormalIfMinimized are needed because Send Coins and Receive Coins
251 // can be triggered from the tray menu, and need to show the GUI to be useful.
17690ea5 252 connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
3479849d 253 connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
382e9e25
PK
254 connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
255 connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
256 connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
257 connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
17690ea5 258 connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
3479849d 259 connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
abf11f79 260
d934e7e3 261 quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
6f959c4c 262 quitAction->setStatusTip(tr("Quit application"));
d934e7e3 263 quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
527137e3 264 quitAction->setMenuRole(QAction::QuitRole);
80fccb0e 265 if (!fIsTestnet)
22f0135d 266 aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin Core"), this);
80fccb0e 267 else
22f0135d 268 aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin Core"), this);
6f959c4c 269 aboutAction->setStatusTip(tr("Show information about Bitcoin"));
01ea41b2 270 aboutAction->setMenuRole(QAction::AboutRole);
c7b1d6bb 271#if QT_VERSION < 0x050000
05fa0de6 272 aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
c7b1d6bb
PK
273#else
274 aboutQtAction = new QAction(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
8abac716 275#endif
6f959c4c 276 aboutQtAction->setStatusTip(tr("Show information about Qt"));
01ea41b2 277 aboutQtAction->setMenuRole(QAction::AboutQtRole);
3479849d 278 optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
6f959c4c 279 optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin"));
527137e3 280 optionsAction->setMenuRole(QAction::PreferencesRole);
80fccb0e
PK
281 if (!fIsTestnet)
282 toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
283 else
284 toggleHideAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&Show / Hide"), this);
6f959c4c 285 toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
8726de26 286
50a38550 287 encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
6f959c4c 288 encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
b7bcaf94 289 encryptWalletAction->setCheckable(true);
50a38550 290 backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
6f959c4c 291 backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
50a38550 292 changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
6f959c4c 293 changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
382e9e25 294 signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
6f959c4c 295 signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
382e9e25 296 verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
6f959c4c 297 verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
382e9e25 298
8ece75ae 299 openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this);
6f959c4c 300 openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
3f323a61 301
66a8829a 302 usedSendingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
4751df0c 303 usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
66a8829a 304 usedReceivingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
4751df0c 305 usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
74fb765e 306
66a8829a 307 openAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_FileIcon), tr("Open &URI..."), this);
4c603586
WL
308 openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
309
f0219813
PK
310 showHelpMessageAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Command-line options"), this);
311 showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options"));
312
3479849d 313 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
3479849d 314 connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
01ea41b2 315 connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
382e9e25 316 connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
86d56349 317 connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
f0219813 318 connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
b7f4b6d3
WL
319#ifdef ENABLE_WALLET
320 if(walletFrame)
321 {
322 connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
323 connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
324 connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
325 connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
326 connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
327 connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
328 connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
329 connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
330 }
331#endif
3f323a61
WL
332}
333
527137e3 334void BitcoinGUI::createMenuBar()
335{
81605d90 336#ifdef Q_OS_MAC
527137e3 337 // Create a decoupled menu bar on Mac which stays even if the window is closed
338 appMenuBar = new QMenuBar();
339#else
340 // Get the main window's menu bar on other platforms
341 appMenuBar = menuBar();
342#endif
343
344 // Configure the menus
345 QMenu *file = appMenuBar->addMenu(tr("&File"));
b7f4b6d3
WL
346 if(walletFrame)
347 {
348 file->addAction(openAction);
349 file->addAction(backupWalletAction);
350 file->addAction(signMessageAction);
351 file->addAction(verifyMessageAction);
352 file->addSeparator();
353 file->addAction(usedSendingAddressesAction);
354 file->addAction(usedReceivingAddressesAction);
355 file->addSeparator();
356 }
527137e3 357 file->addAction(quitAction);
358
359 QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
b7f4b6d3
WL
360 if(walletFrame)
361 {
362 settings->addAction(encryptWalletAction);
363 settings->addAction(changePassphraseAction);
364 settings->addSeparator();
365 }
527137e3 366 settings->addAction(optionsAction);
367
368 QMenu *help = appMenuBar->addMenu(tr("&Help"));
b7f4b6d3
WL
369 if(walletFrame)
370 {
371 help->addAction(openRPCConsoleAction);
b7f4b6d3 372 }
f0219813
PK
373 help->addAction(showHelpMessageAction);
374 help->addSeparator();
527137e3 375 help->addAction(aboutAction);
01ea41b2 376 help->addAction(aboutQtAction);
527137e3 377}
378
379void BitcoinGUI::createToolBars()
380{
b7f4b6d3
WL
381 if(walletFrame)
382 {
383 QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
384 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
385 toolbar->addAction(overviewAction);
386 toolbar->addAction(sendCoinsAction);
387 toolbar->addAction(receiveCoinsAction);
388 toolbar->addAction(historyAction);
389 overviewAction->setChecked(true);
390 }
527137e3 391}
392
ef079e18 393void BitcoinGUI::setClientModel(ClientModel *clientModel)
18cab09a 394{
ef079e18 395 this->clientModel = clientModel;
dead0ff8 396 if(clientModel)
d56c6f31 397 {
f8210212
PK
398 // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
399 // while the client has not yet fully loaded
5968cf5d 400 createTrayIconMenu();
f8210212 401
dead0ff8
WL
402 // Keep up to date with client
403 setNumConnections(clientModel->getNumConnections());
404 connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
18cab09a 405
fe4a6550
WL
406 setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
407 connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
18cab09a 408
309f796b 409 // Receive and report messages from client model
3675588a 410 connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
460c51fd 411
b2bf46d3 412 rpcConsole->setClientModel(clientModel);
b7f4b6d3
WL
413#ifdef ENABLE_WALLET
414 if(walletFrame)
415 {
416 walletFrame->setClientModel(clientModel);
417 }
418#endif
dead0ff8 419 }
ef079e18
WL
420}
421
b7f4b6d3 422#ifdef ENABLE_WALLET
67155d92 423bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
ef079e18 424{
b7f4b6d3
WL
425 if(!walletFrame)
426 return false;
146ba964 427 setWalletActionsEnabled(true);
67155d92
EL
428 return walletFrame->addWallet(name, walletModel);
429}
430
431bool BitcoinGUI::setCurrentWallet(const QString& name)
432{
b7f4b6d3
WL
433 if(!walletFrame)
434 return false;
67155d92
EL
435 return walletFrame->setCurrentWallet(name);
436}
437
438void BitcoinGUI::removeAllWallets()
439{
b7f4b6d3
WL
440 if(!walletFrame)
441 return;
146ba964 442 setWalletActionsEnabled(false);
67155d92 443 walletFrame->removeAllWallets();
18cab09a 444}
b7f4b6d3 445#endif
18cab09a 446
146ba964
WL
447void BitcoinGUI::setWalletActionsEnabled(bool enabled)
448{
449 overviewAction->setEnabled(enabled);
450 sendCoinsAction->setEnabled(enabled);
451 receiveCoinsAction->setEnabled(enabled);
452 historyAction->setEnabled(enabled);
453 encryptWalletAction->setEnabled(enabled);
454 backupWalletAction->setEnabled(enabled);
455 changePassphraseAction->setEnabled(enabled);
456 signMessageAction->setEnabled(enabled);
457 verifyMessageAction->setEnabled(enabled);
458 usedSendingAddressesAction->setEnabled(enabled);
459 usedReceivingAddressesAction->setEnabled(enabled);
460 openAction->setEnabled(enabled);
461}
462
80fccb0e 463void BitcoinGUI::createTrayIcon(bool fIsTestnet)
3f323a61 464{
81605d90 465#ifndef Q_OS_MAC
3f323a61 466 trayIcon = new QSystemTrayIcon(this);
f8210212 467
80fccb0e
PK
468 if (!fIsTestnet)
469 {
470 trayIcon->setToolTip(tr("Bitcoin client"));
471 trayIcon->setIcon(QIcon(":/icons/toolbar"));
472 }
473 else
474 {
475 trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]"));
476 trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
477 }
478
f8210212
PK
479 trayIcon->show();
480#endif
481
ccd1372d 482 notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
f8210212
PK
483}
484
485void BitcoinGUI::createTrayIconMenu()
486{
487 QMenu *trayIconMenu;
488#ifndef Q_OS_MAC
5968cf5d
PK
489 // return if trayIcon is unset (only on non-Mac OSes)
490 if (!trayIcon)
491 return;
492
f8210212
PK
493 trayIconMenu = new QMenu(this);
494 trayIcon->setContextMenu(trayIconMenu);
495
352083cb
WL
496 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
497 this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
527137e3 498#else
499 // Note: On Mac, the dock icon is used to provide the tray's functionality.
500 MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
4d17a1b0 501 dockIconHandler->setMainWindow((QMainWindow *)this);
527137e3 502 trayIconMenu = dockIconHandler->dockMenu();
503#endif
504
505 // Configuration of the tray icon (or dock icon) icon menu
86d56349 506 trayIconMenu->addAction(toggleHideAction);
527137e3 507 trayIconMenu->addSeparator();
f5f2d741
WL
508 trayIconMenu->addAction(sendCoinsAction);
509 trayIconMenu->addAction(receiveCoinsAction);
2bc4fd60 510 trayIconMenu->addSeparator();
47894585 511 trayIconMenu->addAction(signMessageAction);
f5f2d741 512 trayIconMenu->addAction(verifyMessageAction);
527137e3 513 trayIconMenu->addSeparator();
514 trayIconMenu->addAction(optionsAction);
f5f2d741 515 trayIconMenu->addAction(openRPCConsoleAction);
81605d90 516#ifndef Q_OS_MAC // This is built-in on Mac
527137e3 517 trayIconMenu->addSeparator();
518 trayIconMenu->addAction(quitAction);
519#endif
3f323a61
WL
520}
521
81605d90 522#ifndef Q_OS_MAC
352083cb
WL
523void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
524{
b0849613 525 if(reason == QSystemTrayIcon::Trigger)
352083cb 526 {
e273c512 527 // Click on system tray icon triggers show/hide of the main window
86d56349 528 toggleHideAction->trigger();
352083cb
WL
529 }
530}
527137e3 531#endif
352083cb 532
af943776
WL
533void BitcoinGUI::optionsClicked()
534{
dead0ff8
WL
535 if(!clientModel || !clientModel->getOptionsModel())
536 return;
309f796b
PK
537
538 OptionsDialog dlg(this);
ef079e18 539 dlg.setModel(clientModel->getOptionsModel());
8812ce7b 540 dlg.exec();
af943776
WL
541}
542
8812ce7b 543void BitcoinGUI::aboutClicked()
af943776 544{
309f796b
PK
545 if(!clientModel)
546 return;
547
548 AboutDialog dlg(this);
0052fe7b 549 dlg.setModel(clientModel);
8812ce7b 550 dlg.exec();
af943776
WL
551}
552
f0219813
PK
553void BitcoinGUI::showHelpMessageClicked()
554{
555 HelpMessageDialog *help = new HelpMessageDialog(this);
556 help->setAttribute(Qt::WA_DeleteOnClose);
557 help->show();
558}
559
b7f4b6d3 560#ifdef ENABLE_WALLET
4c603586
WL
561void BitcoinGUI::openClicked()
562{
309f796b 563 OpenURIDialog dlg(this);
4c603586
WL
564 if(dlg.exec())
565 {
566 emit receivedURI(dlg.getURI());
567 }
568}
569
67155d92
EL
570void BitcoinGUI::gotoOverviewPage()
571{
16314593 572 overviewAction->setChecked(true);
67155d92
EL
573 if (walletFrame) walletFrame->gotoOverviewPage();
574}
575
576void BitcoinGUI::gotoHistoryPage()
577{
16314593 578 historyAction->setChecked(true);
67155d92
EL
579 if (walletFrame) walletFrame->gotoHistoryPage();
580}
581
67155d92
EL
582void BitcoinGUI::gotoReceiveCoinsPage()
583{
16314593 584 receiveCoinsAction->setChecked(true);
67155d92
EL
585 if (walletFrame) walletFrame->gotoReceiveCoinsPage();
586}
587
abf11f79 588void BitcoinGUI::gotoSendCoinsPage(QString addr)
67155d92 589{
16314593 590 sendCoinsAction->setChecked(true);
abf11f79 591 if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
67155d92
EL
592}
593
594void BitcoinGUI::gotoSignMessageTab(QString addr)
595{
596 if (walletFrame) walletFrame->gotoSignMessageTab(addr);
597}
598
599void BitcoinGUI::gotoVerifyMessageTab(QString addr)
600{
0dcf9e53 601 if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
67155d92 602}
b7f4b6d3 603#endif
67155d92 604
1a6d504a
WL
605void BitcoinGUI::setNumConnections(int count)
606{
b1ef1b24
WL
607 QString icon;
608 switch(count)
609 {
89c94b55
WL
610 case 0: icon = ":/icons/connect_0"; break;
611 case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
612 case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
613 case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
614 default: icon = ":/icons/connect_4"; break;
b1ef1b24 615 }
ae8adeb9 616 labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
00f4f8d5 617 labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
1a6d504a
WL
618}
619
fe4a6550 620void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
1a6d504a 621{
6f959c4c
PK
622 // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text)
623 statusBar()->clearMessage();
624
4881353e
PK
625 // Acquire current block source
626 enum BlockSource blockSource = clientModel->getBlockSource();
627 switch (blockSource) {
628 case BLOCK_SOURCE_NETWORK:
629 progressBarLabel->setText(tr("Synchronizing with network..."));
630 break;
631 case BLOCK_SOURCE_DISK:
632 progressBarLabel->setText(tr("Importing blocks from disk..."));
633 break;
634 case BLOCK_SOURCE_REINDEX:
635 progressBarLabel->setText(tr("Reindexing blocks on disk..."));
636 break;
637 case BLOCK_SOURCE_NONE:
638 // Case: not Importing, not Reindexing and no network connection
639 progressBarLabel->setText(tr("No block source available..."));
640 break;
068ed1e8
PK
641 }
642
5df0b03c
WL
643 QString tooltip;
644
84c8506e 645 QDateTime lastBlockDate = clientModel->getLastBlockDate();
24cde0b7
WL
646 QDateTime currentDate = QDateTime::currentDateTime();
647 int secs = lastBlockDate.secsTo(currentDate);
84c8506e 648
24cde0b7 649 if(count < nTotalBlocks)
84c8506e 650 {
24cde0b7 651 tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks);
84c8506e
WL
652 }
653 else
654 {
24cde0b7 655 tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
84c8506e 656 }
a75e1e32 657
b0849613 658 // Set icon state: spinning if catching up, tick otherwise
b9700672 659 if(secs < 90*60 && count >= nTotalBlocks)
a75e1e32 660 {
3793fa09 661 tooltip = tr("Up to date") + QString(".<br>") + tooltip;
e72c6a18 662 labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
c26f3a9b 663
b7f4b6d3
WL
664#ifdef ENABLE_WALLET
665 if(walletFrame)
666 walletFrame->showOutOfSyncWarning(false);
667#endif
24cde0b7
WL
668
669 progressBarLabel->setVisible(false);
670 progressBar->setVisible(false);
a75e1e32 671 }
2351a3fc
WL
672 else
673 {
24cde0b7
WL
674 // Represent time from last generated block in human readable text
675 QString timeBehindText;
a1465ac8
WL
676 const int HOUR_IN_SECONDS = 60*60;
677 const int DAY_IN_SECONDS = 24*60*60;
678 const int WEEK_IN_SECONDS = 7*24*60*60;
679 const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
680 if(secs < 2*DAY_IN_SECONDS)
24cde0b7 681 {
a1465ac8 682 timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS);
24cde0b7 683 }
a1465ac8 684 else if(secs < 2*WEEK_IN_SECONDS)
24cde0b7 685 {
a1465ac8
WL
686 timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS);
687 }
688 else if(secs < YEAR_IN_SECONDS)
689 {
690 timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS);
24cde0b7
WL
691 }
692 else
693 {
a1465ac8
WL
694 int years = secs / YEAR_IN_SECONDS;
695 int remainder = secs % YEAR_IN_SECONDS;
696 timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS));
24cde0b7
WL
697 }
698
24cde0b7
WL
699 progressBarLabel->setVisible(true);
700 progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
9f2467ad
PW
701 progressBar->setMaximum(1000000000);
702 progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
24cde0b7
WL
703 progressBar->setVisible(true);
704
3793fa09 705 tooltip = tr("Catching up...") + QString("<br>") + tooltip;
24cde0b7 706 if(count != prevBlocks)
f10b2d70
WL
707 {
708 labelBlocksIcon->setPixmap(QIcon(QString(
709 ":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')))
710 .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
711 spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
712 }
24cde0b7 713 prevBlocks = count;
c26f3a9b 714
b7f4b6d3
WL
715#ifdef ENABLE_WALLET
716 if(walletFrame)
717 walletFrame->showOutOfSyncWarning(true);
718#endif
a75e1e32 719
3793fa09 720 tooltip += QString("<br>");
24cde0b7
WL
721 tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
722 tooltip += QString("<br>");
723 tooltip += tr("Transactions after this will not yet be visible.");
71ba9abb 724 }
8dcffd4d 725
3793fa09
WL
726 // Don't word-wrap this (fixed-width) tooltip
727 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
728
8dcffd4d 729 labelBlocksIcon->setToolTip(tooltip);
5df0b03c
WL
730 progressBarLabel->setToolTip(tooltip);
731 progressBar->setToolTip(tooltip);
1a6d504a
WL
732}
733
f7f3a96b 734void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
6630c1cb 735{
8d643c90 736 QString strTitle = tr("Bitcoin"); // default title
5350ea41
PK
737 // Default to information icon
738 int nMBoxIcon = QMessageBox::Information;
739 int nNotifyIcon = Notificator::Information;
740
8d643c90 741 QString msgType;
b26f9d89
PK
742
743 // Prefer supplied title over style based title
744 if (!title.isEmpty()) {
745 msgType = title;
746 }
747 else {
748 switch (style) {
749 case CClientUIInterface::MSG_ERROR:
750 msgType = tr("Error");
751 break;
752 case CClientUIInterface::MSG_WARNING:
753 msgType = tr("Warning");
754 break;
755 case CClientUIInterface::MSG_INFORMATION:
756 msgType = tr("Information");
757 break;
758 default:
759 break;
760 }
5350ea41 761 }
b26f9d89 762 // Append title to "Bitcoin - "
8d643c90
PK
763 if (!msgType.isEmpty())
764 strTitle += " - " + msgType;
5350ea41
PK
765
766 // Check for error/warning icon
767 if (style & CClientUIInterface::ICON_ERROR) {
768 nMBoxIcon = QMessageBox::Critical;
769 nNotifyIcon = Notificator::Critical;
7cfbe1fe 770 }
5350ea41
PK
771 else if (style & CClientUIInterface::ICON_WARNING) {
772 nMBoxIcon = QMessageBox::Warning;
773 nNotifyIcon = Notificator::Warning;
774 }
775
776 // Display message
3675588a 777 if (style & CClientUIInterface::MODAL) {
5350ea41
PK
778 // Check for buttons, use OK as default, if none was supplied
779 QMessageBox::StandardButton buttons;
780 if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
781 buttons = QMessageBox::Ok;
782
1ad26362
WL
783 // Ensure we get users attention, but only if main window is visible
784 // as we don't want to pop up the main window for messages that happen before
785 // initialization is finished.
786 if(!(style & CClientUIInterface::NOSHOWGUI))
787 showNormalIfMinimized();
b26f9d89 788 QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
f7f3a96b
PW
789 int r = mBox.exec();
790 if (ret != NULL)
791 *ret = r == QMessageBox::Ok;
5350ea41
PK
792 }
793 else
794 notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
6630c1cb 795}
352083cb
WL
796
797void BitcoinGUI::changeEvent(QEvent *e)
798{
08ed96d8 799 QMainWindow::changeEvent(e);
81605d90 800#ifndef Q_OS_MAC // Ignored on Mac
405ce5a8 801 if(e->type() == QEvent::WindowStateChange)
352083cb 802 {
405ce5a8 803 if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray())
352083cb 804 {
83d1d1a9 805 QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
08ed96d8 806 if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
8e86dca2 807 {
08ed96d8
WL
808 QTimer::singleShot(0, this, SLOT(hide()));
809 e->ignore();
352083cb
WL
810 }
811 }
812 }
527137e3 813#endif
352083cb
WL
814}
815
816void BitcoinGUI::closeEvent(QCloseEvent *event)
817{
dead0ff8 818 if(clientModel)
352083cb 819 {
81605d90 820#ifndef Q_OS_MAC // Ignored on Mac
dead0ff8
WL
821 if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
822 !clientModel->getOptionsModel()->getMinimizeOnClose())
823 {
1ce04488 824 QApplication::quit();
dead0ff8 825 }
527137e3 826#endif
dead0ff8 827 }
352083cb
WL
828 QMainWindow::closeEvent(event);
829}
b7726d92 830
b7f4b6d3 831#ifdef ENABLE_WALLET
67155d92 832void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address)
725d460e 833{
abf11f79 834 // On new transaction, make an info balloon
50ecd7b6
PK
835 message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
836 tr("Date: %1\n"
837 "Amount: %2\n"
838 "Type: %3\n"
839 "Address: %4\n")
840 .arg(date)
67155d92 841 .arg(BitcoinUnits::formatWithUnit(unit, amount, true))
50ecd7b6
PK
842 .arg(type)
843 .arg(address), CClientUIInterface::MSG_INFORMATION);
725d460e 844}
b7f4b6d3 845#endif
64c8b699 846
db7f0234
WL
847void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
848{
fa2544e7 849 // Accept only URIs
db7f0234
WL
850 if(event->mimeData()->hasUrls())
851 event->acceptProposedAction();
852}
853
854void BitcoinGUI::dropEvent(QDropEvent *event)
855{
856 if(event->mimeData()->hasUrls())
857 {
4c603586 858 foreach(const QUrl &uri, event->mimeData()->urls())
db7f0234 859 {
4c603586 860 emit receivedURI(uri.toString());
db7f0234
WL
861 }
862 }
db7f0234
WL
863 event->acceptProposedAction();
864}
865
6f959c4c
PK
866bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
867{
868 // Catch status tip events
869 if (event->type() == QEvent::StatusTip)
870 {
871 // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
35ed704d 872 if (progressBarLabel->isVisible() || progressBar->isVisible())
6f959c4c
PK
873 return true;
874 }
875 return QMainWindow::eventFilter(object, event);
876}
877
b7f4b6d3 878#ifdef ENABLE_WALLET
2384a286 879bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
7d145a0f 880{
2384a286 881 // URI has to be valid
b7f4b6d3 882 if (walletFrame && walletFrame->handlePaymentRequest(recipient))
2384a286
PK
883 {
884 showNormalIfMinimized();
885 gotoSendCoinsPage();
886 return true;
887 }
888 else
889 return false;
a41d5fe0
GA
890}
891
ae8adeb9
WL
892void BitcoinGUI::setEncryptionStatus(int status)
893{
894 switch(status)
895 {
896 case WalletModel::Unencrypted:
897 labelEncryptionIcon->hide();
b7bcaf94
WL
898 encryptWalletAction->setChecked(false);
899 changePassphraseAction->setEnabled(false);
900 encryptWalletAction->setEnabled(true);
ae8adeb9
WL
901 break;
902 case WalletModel::Unlocked:
903 labelEncryptionIcon->show();
904 labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
905 labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
b7bcaf94
WL
906 encryptWalletAction->setChecked(true);
907 changePassphraseAction->setEnabled(true);
908 encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
ae8adeb9
WL
909 break;
910 case WalletModel::Locked:
911 labelEncryptionIcon->show();
912 labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
913 labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
b7bcaf94
WL
914 encryptWalletAction->setChecked(true);
915 changePassphraseAction->setEnabled(true);
916 encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
ae8adeb9
WL
917 break;
918 }
919}
b7f4b6d3 920#endif
b7bcaf94 921
d2e6dd6c 922void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
17690ea5 923{
d2e6dd6c
PK
924 // activateWindow() (sometimes) helps with keyboard focus on Windows
925 if (isHidden())
926 {
17690ea5 927 show();
d2e6dd6c
PK
928 activateWindow();
929 }
930 else if (isMinimized())
931 {
17690ea5 932 showNormal();
d2e6dd6c
PK
933 activateWindow();
934 }
935 else if (GUIUtil::isObscured(this))
936 {
937 raise();
938 activateWindow();
939 }
940 else if(fToggleHidden)
941 hide();
942}
943
944void BitcoinGUI::toggleHidden()
945{
946 showNormalIfMinimized(true);
17690ea5 947}
723035bb
GA
948
949void BitcoinGUI::detectShutdown()
950{
951 if (ShutdownRequested())
9a2305a1
WL
952 {
953 if(rpcConsole)
954 rpcConsole->hide();
955 qApp->quit();
956 }
723035bb 957}
35ecf854
WL
958
959static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
960{
961 bool modal = (style & CClientUIInterface::MODAL);
962 bool ret = false;
963 // In case of modal message, use blocking connection to wait for user to click a button
964 QMetaObject::invokeMethod(gui, "message",
965 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
966 Q_ARG(QString, QString::fromStdString(caption)),
967 Q_ARG(QString, QString::fromStdString(message)),
968 Q_ARG(unsigned int, style),
969 Q_ARG(bool*, &ret));
970 return ret;
971}
972
973void BitcoinGUI::subscribeToCoreSignals()
974{
975 // Connect signals to client
976 uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
977}
978
979void BitcoinGUI::unsubscribeFromCoreSignals()
980{
981 // Disconnect signals from client
982 uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
983}
This page took 0.266182 seconds and 4 git commands to generate.