Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
bitcoingui.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Distributed under the MIT/X11 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 "notificator.h"
12 #include "openuridialog.h"
13 #include "optionsdialog.h"
14 #include "optionsmodel.h"
15 #include "rpcconsole.h"
16 #include "utilitydialog.h"
17 #ifdef ENABLE_WALLET
18 #include "walletframe.h"
19 #include "walletmodel.h"
20 #endif
21 
22 #ifdef Q_OS_MAC
23 #include "macdockiconhandler.h"
24 #endif
25 
26 #include "init.h"
27 #include "ui_interface.h"
28 
29 #include <iostream>
30 
31 #include <QApplication>
32 #include <QDateTime>
33 #include <QDesktopWidget>
34 #include <QDragEnterEvent>
35 #include <QIcon>
36 #include <QLabel>
37 #include <QListWidget>
38 #include <QMenu>
39 #include <QMenuBar>
40 #include <QMessageBox>
41 #include <QMimeData>
42 #include <QProgressBar>
43 #include <QSettings>
44 #include <QStackedWidget>
45 #include <QStatusBar>
46 #include <QStyle>
47 #include <QTimer>
48 #include <QToolBar>
49 #include <QVBoxLayout>
50 
51 #if QT_VERSION < 0x050000
52 #include <QUrl>
53 #include <QTextDocument>
54 #else
55 #include <QUrlQuery>
56 #endif
57 
58 const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
59 
60 BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
61  QMainWindow(parent),
62  clientModel(0),
63  walletFrame(0),
64  encryptWalletAction(0),
65  changePassphraseAction(0),
66  aboutQtAction(0),
67  trayIcon(0),
68  notificator(0),
69  rpcConsole(0),
70  prevBlocks(0),
71  spinnerFrame(0)
72 {
73  GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
74 
75  QString windowTitle = tr("Master 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 
89  if (!fIsTestnet)
90  {
91 #ifndef Q_OS_MAC
92  QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
93  setWindowIcon(QIcon(":icons/bitcoin"));
94 #else
95  MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin"));
96 #endif
97  }
98  else
99  {
100  windowTitle += " " + tr("[testnet]");
101 #ifndef Q_OS_MAC
102  QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
103  setWindowIcon(QIcon(":icons/bitcoin_testnet"));
104 #else
105  MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
106 #endif
107  }
108  setWindowTitle(windowTitle);
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
115 
116  rpcConsole = new RPCConsole(enableWallet ? this : 0);
117 #ifdef ENABLE_WALLET
118  if(enableWallet)
119  {
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  }
131 
132  // Accept D&D of URIs
133  setAcceptDrops(true);
134 
135  // Create actions for the toolbar, menu bar and tray/dock icon
136  // Needs walletFrame to be initialized
137  createActions(fIsTestnet);
138 
139  // Create application menu bar
140  createMenuBar();
141 
142  // Create the toolbars
143  createToolBars();
144 
145  // Create system tray icon and notification
146  createTrayIcon(fIsTestnet);
147 
148  // Create status bar
149  statusBar();
150 
151  // Status bar notification icons
152  QFrame *frameBlocks = new QFrame();
153  frameBlocks->setContentsMargins(0,0,0,0);
154  frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
155  QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
156  frameBlocksLayout->setContentsMargins(3,0,3,0);
157  frameBlocksLayout->setSpacing(3);
158  labelEncryptionIcon = new QLabel();
160  labelBlocksIcon = new QLabel();
161  frameBlocksLayout->addStretch();
162  frameBlocksLayout->addWidget(labelEncryptionIcon);
163  frameBlocksLayout->addStretch();
164  frameBlocksLayout->addWidget(labelConnectionsIcon);
165  frameBlocksLayout->addStretch();
166  frameBlocksLayout->addWidget(labelBlocksIcon);
167  frameBlocksLayout->addStretch();
168 
169  // Progress bar and label for blocks download
170  progressBarLabel = new QLabel();
171  progressBarLabel->setVisible(false);
172  progressBar = new QProgressBar();
173  progressBar->setAlignment(Qt::AlignCenter);
174  progressBar->setVisible(false);
175 
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
179  QString curStyle = QApplication::style()->metaObject()->className();
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 
185  statusBar()->addWidget(progressBarLabel);
186  statusBar()->addWidget(progressBar);
187  statusBar()->addPermanentWidget(frameBlocks);
188 
189  connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
190 
191  // prevents an oben debug window from becoming stuck/unusable on client shutdown
192  connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
193 
194  // Install event filter to be able to catch status tip events (QEvent::StatusTip)
195  this->installEventFilter(this);
196 
197  // Initially wallet actions should be disabled
199 
200  // Subscribe to notifications from core
202 }
203 
205 {
206  // Unsubscribe from notifications from core
208 
209  GUIUtil::saveWindowGeometry("nWindow", this);
210  if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
211  trayIcon->hide();
212 #ifdef Q_OS_MAC
213  delete appMenuBar;
215 #endif
216 }
217 
218 void BitcoinGUI::createActions(bool fIsTestnet)
219 {
220  QActionGroup *tabGroup = new QActionGroup(this);
221 
222  overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
223  overviewAction->setStatusTip(tr("Show general overview of wallet"));
224  overviewAction->setToolTip(overviewAction->statusTip());
225  overviewAction->setCheckable(true);
226  overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
227  tabGroup->addAction(overviewAction);
228 
229  balancesAction = new QAction(QIcon(":/icons/balances"), tr("&Balances"), this);
230  balancesAction->setStatusTip(tr("Show Master Protocol balances"));
231  balancesAction->setToolTip(balancesAction->statusTip());
232  balancesAction->setCheckable(true);
233  balancesAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
234  tabGroup->addAction(balancesAction);
235 
236  sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this);
237  sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
238  sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
239  sendCoinsAction->setCheckable(true);
240  sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
241  tabGroup->addAction(sendCoinsAction);
242 
243  receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
244  receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
245  receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
246  receiveCoinsAction->setCheckable(true);
247  receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
248  tabGroup->addAction(receiveCoinsAction);
249 
250  historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
251  historyAction->setStatusTip(tr("Browse transaction history"));
252  historyAction->setToolTip(historyAction->statusTip());
253  historyAction->setCheckable(true);
254  historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
255  tabGroup->addAction(historyAction);
256 
257  // These showNormalIfMinimized are needed because Send Coins and Receive Coins
258  // can be triggered from the tray menu, and need to show the GUI to be useful.
259  connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
260  connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
261  connect(balancesAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
262  connect(balancesAction, SIGNAL(triggered()), this, SLOT(gotoBalancesPage()));
263  connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
264  connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
265  connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
266  connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
267  connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
268  connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
269 
270  quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
271  quitAction->setStatusTip(tr("Quit application"));
272  quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
273  quitAction->setMenuRole(QAction::QuitRole);
274  if (!fIsTestnet)
275  aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Master Core"), this);
276  else
277  aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Master Core"), this);
278  aboutAction->setStatusTip(tr("Show information about Master Core"));
279  aboutAction->setMenuRole(QAction::AboutRole);
280 #if QT_VERSION < 0x050000
281  aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
282 #else
283  aboutQtAction = new QAction(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
284 #endif
285  aboutQtAction->setStatusTip(tr("Show information about Qt"));
286  aboutQtAction->setMenuRole(QAction::AboutQtRole);
287  optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
288  optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin"));
289  optionsAction->setMenuRole(QAction::PreferencesRole);
290  if (!fIsTestnet)
291  toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
292  else
293  toggleHideAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&Show / Hide"), this);
294  toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
295 
296  encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
297  encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
298  encryptWalletAction->setCheckable(true);
299  backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
300  backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
301  changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
302  changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
303  signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
304  signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
305  verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
306  verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
307 
308  openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this);
309  openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
310 
311  usedSendingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
312  usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
313  usedReceivingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
314  usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
315 
316  openAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_FileIcon), tr("Open &URI..."), this);
317  openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
318 
319  showHelpMessageAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Command-line options"), this);
320  showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options"));
321 
322  connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
323  connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
324  connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
325  connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
326  connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
327  connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
328 #ifdef ENABLE_WALLET
329  if(walletFrame)
330  {
331  connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
332  connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
333  connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
334  connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
335  connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
336  connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
337  connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
338  connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
339  }
340 #endif
341 }
342 
344 {
345 #ifdef Q_OS_MAC
346  // Create a decoupled menu bar on Mac which stays even if the window is closed
347  appMenuBar = new QMenuBar();
348 #else
349  // Get the main window's menu bar on other platforms
350  appMenuBar = menuBar();
351 #endif
352 
353  // Configure the menus
354  QMenu *file = appMenuBar->addMenu(tr("&File"));
355  if(walletFrame)
356  {
357  file->addAction(openAction);
358  file->addAction(backupWalletAction);
359  file->addAction(signMessageAction);
360  file->addAction(verifyMessageAction);
361  file->addSeparator();
362  file->addAction(usedSendingAddressesAction);
363  file->addAction(usedReceivingAddressesAction);
364  file->addSeparator();
365  }
366  file->addAction(quitAction);
367 
368  QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
369  if(walletFrame)
370  {
371  settings->addAction(encryptWalletAction);
372  settings->addAction(changePassphraseAction);
373  settings->addSeparator();
374  }
375  settings->addAction(optionsAction);
376 
377  QMenu *help = appMenuBar->addMenu(tr("&Help"));
378  if(walletFrame)
379  {
380  help->addAction(openRPCConsoleAction);
381  }
382  help->addAction(showHelpMessageAction);
383  help->addSeparator();
384  help->addAction(aboutAction);
385  help->addAction(aboutQtAction);
386 }
387 
389 {
390  if(walletFrame)
391  {
392  QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
393  toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
394  toolbar->addAction(overviewAction);
395  toolbar->addAction(balancesAction);
396  toolbar->addAction(sendCoinsAction);
397  toolbar->addAction(receiveCoinsAction);
398  toolbar->addAction(historyAction);
399  overviewAction->setChecked(true);
400  }
401 }
402 
404 {
405  this->clientModel = clientModel;
406  if(clientModel)
407  {
408  // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
409  // while the client has not yet fully loaded
411 
412  // Keep up to date with client
413  setNumConnections(clientModel->getNumConnections());
414  connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
415 
416  setNumBlocks(clientModel->getNumBlocks());
417  connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
418 
419  // Receive and report messages from client model
420  connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
421 
422  rpcConsole->setClientModel(clientModel);
423 #ifdef ENABLE_WALLET
424  if(walletFrame)
425  {
426  walletFrame->setClientModel(clientModel);
427  }
428 #endif
429  }
430 }
431 
432 #ifdef ENABLE_WALLET
433 bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
434 {
435  if(!walletFrame)
436  return false;
438  return walletFrame->addWallet(name, walletModel);
439 }
440 
441 bool BitcoinGUI::setCurrentWallet(const QString& name)
442 {
443  if(!walletFrame)
444  return false;
445  return walletFrame->setCurrentWallet(name);
446 }
447 
448 void BitcoinGUI::removeAllWallets()
449 {
450  if(!walletFrame)
451  return;
454 }
455 #endif
456 
458 {
459  overviewAction->setEnabled(enabled);
460  balancesAction->setEnabled(enabled);
461  sendCoinsAction->setEnabled(enabled);
462  receiveCoinsAction->setEnabled(enabled);
463  historyAction->setEnabled(enabled);
464  encryptWalletAction->setEnabled(enabled);
465  backupWalletAction->setEnabled(enabled);
466  changePassphraseAction->setEnabled(enabled);
467  signMessageAction->setEnabled(enabled);
468  verifyMessageAction->setEnabled(enabled);
469  usedSendingAddressesAction->setEnabled(enabled);
470  usedReceivingAddressesAction->setEnabled(enabled);
471  openAction->setEnabled(enabled);
472 }
473 
474 void BitcoinGUI::createTrayIcon(bool fIsTestnet)
475 {
476 #ifndef Q_OS_MAC
477  trayIcon = new QSystemTrayIcon(this);
478 
479  if (!fIsTestnet)
480  {
481  trayIcon->setToolTip(tr("Bitcoin client"));
482  trayIcon->setIcon(QIcon(":/icons/toolbar"));
483  }
484  else
485  {
486  trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]"));
487  trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
488  }
489 
490  trayIcon->show();
491 #endif
492 
493  notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
494 }
495 
497 {
498  QMenu *trayIconMenu;
499 #ifndef Q_OS_MAC
500  // return if trayIcon is unset (only on non-Mac OSes)
501  if (!trayIcon)
502  return;
503 
504  trayIconMenu = new QMenu(this);
505  trayIcon->setContextMenu(trayIconMenu);
506 
507  connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
508  this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
509 #else
510  // Note: On Mac, the dock icon is used to provide the tray's functionality.
512  dockIconHandler->setMainWindow((QMainWindow *)this);
513  trayIconMenu = dockIconHandler->dockMenu();
514 #endif
515 
516  // Configuration of the tray icon (or dock icon) icon menu
517  trayIconMenu->addAction(toggleHideAction);
518  trayIconMenu->addSeparator();
519  trayIconMenu->addAction(sendCoinsAction);
520  trayIconMenu->addAction(receiveCoinsAction);
521  trayIconMenu->addSeparator();
522  trayIconMenu->addAction(signMessageAction);
523  trayIconMenu->addAction(verifyMessageAction);
524  trayIconMenu->addSeparator();
525  trayIconMenu->addAction(optionsAction);
526  trayIconMenu->addAction(openRPCConsoleAction);
527 #ifndef Q_OS_MAC // This is built-in on Mac
528  trayIconMenu->addSeparator();
529  trayIconMenu->addAction(quitAction);
530 #endif
531 }
532 
533 #ifndef Q_OS_MAC
534 void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
535 {
536  if(reason == QSystemTrayIcon::Trigger)
537  {
538  // Click on system tray icon triggers show/hide of the main window
539  toggleHideAction->trigger();
540  }
541 }
542 #endif
543 
545 {
547  return;
548 
549  OptionsDialog dlg(this);
551  dlg.exec();
552 }
553 
555 {
556  if(!clientModel)
557  return;
558 
559  AboutDialog dlg(this);
560  dlg.setModel(clientModel);
561  dlg.exec();
562 }
563 
565 {
567  help->setAttribute(Qt::WA_DeleteOnClose);
568  help->show();
569 }
570 
571 #ifdef ENABLE_WALLET
572 void BitcoinGUI::openClicked()
573 {
574  OpenURIDialog dlg(this);
575  if(dlg.exec())
576  {
577  emit receivedURI(dlg.getURI());
578  }
579 }
580 
581 void BitcoinGUI::gotoOverviewPage()
582 {
583  overviewAction->setChecked(true);
585 }
586 
587 void BitcoinGUI::gotoBalancesPage()
588 {
589  balancesAction->setChecked(true);
591 }
592 
593 void BitcoinGUI::gotoHistoryPage()
594 {
595  historyAction->setChecked(true);
597 }
598 
599 void BitcoinGUI::gotoReceiveCoinsPage()
600 {
601  receiveCoinsAction->setChecked(true);
603 }
604 
605 void BitcoinGUI::gotoSendCoinsPage(QString addr)
606 {
607  sendCoinsAction->setChecked(true);
609 }
610 
611 void BitcoinGUI::gotoSignMessageTab(QString addr)
612 {
614 }
615 
616 void BitcoinGUI::gotoVerifyMessageTab(QString addr)
617 {
619 }
620 #endif
621 
623 {
624  QString icon;
625  switch(count)
626  {
627  case 0: icon = ":/icons/connect_0"; break;
628  case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
629  case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
630  case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
631  default: icon = ":/icons/connect_4"; break;
632  }
633  labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
634  labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
635 }
636 
638 {
639  // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text)
640  statusBar()->clearMessage();
641 
642  // Acquire current block source
643  enum BlockSource blockSource = clientModel->getBlockSource();
644  switch (blockSource) {
646  progressBarLabel->setText(tr("Synchronizing with network..."));
647  break;
648  case BLOCK_SOURCE_DISK:
649  progressBarLabel->setText(tr("Importing blocks from disk..."));
650  break;
652  progressBarLabel->setText(tr("Reindexing blocks on disk..."));
653  break;
654  case BLOCK_SOURCE_NONE:
655  // Case: not Importing, not Reindexing and no network connection
656  progressBarLabel->setText(tr("No block source available..."));
657  break;
658  }
659 
660  QString tooltip;
661 
662  QDateTime lastBlockDate = clientModel->getLastBlockDate();
663  QDateTime currentDate = QDateTime::currentDateTime();
664  int secs = lastBlockDate.secsTo(currentDate);
665 
666  tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
667 
668  // Set icon state: spinning if catching up, tick otherwise
669  if(secs < 90*60)
670  {
671  tooltip = tr("Up to date") + QString(".<br>") + tooltip;
672  labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
673 
674 #ifdef ENABLE_WALLET
675  if(walletFrame)
677 #endif
678 
679  progressBarLabel->setVisible(false);
680  progressBar->setVisible(false);
681  }
682  else
683  {
684  // Represent time from last generated block in human readable text
685  QString timeBehindText;
686  const int HOUR_IN_SECONDS = 60*60;
687  const int DAY_IN_SECONDS = 24*60*60;
688  const int WEEK_IN_SECONDS = 7*24*60*60;
689  const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
690  if(secs < 2*DAY_IN_SECONDS)
691  {
692  timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS);
693  }
694  else if(secs < 2*WEEK_IN_SECONDS)
695  {
696  timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS);
697  }
698  else if(secs < YEAR_IN_SECONDS)
699  {
700  timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS);
701  }
702  else
703  {
704  int years = secs / YEAR_IN_SECONDS;
705  int remainder = secs % YEAR_IN_SECONDS;
706  timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS));
707  }
708 
709  progressBarLabel->setVisible(true);
710  progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
711  progressBar->setMaximum(1000000000);
712  progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
713  progressBar->setVisible(true);
714 
715  tooltip = tr("Catching up...") + QString("<br>") + tooltip;
716  if(count != prevBlocks)
717  {
718  labelBlocksIcon->setPixmap(QIcon(QString(
719  ":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')))
722  }
723  prevBlocks = count;
724 
725 #ifdef ENABLE_WALLET
726  if(walletFrame)
728 #endif
729 
730  tooltip += QString("<br>");
731  tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
732  tooltip += QString("<br>");
733  tooltip += tr("Transactions after this will not yet be visible.");
734  }
735 
736  // Don't word-wrap this (fixed-width) tooltip
737  tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
738 
739  labelBlocksIcon->setToolTip(tooltip);
740  progressBarLabel->setToolTip(tooltip);
741  progressBar->setToolTip(tooltip);
742 }
743 
744 void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
745 {
746  QString strTitle = tr("Bitcoin"); // default title
747  // Default to information icon
748  int nMBoxIcon = QMessageBox::Information;
749  int nNotifyIcon = Notificator::Information;
750 
751  QString msgType;
752 
753  // Prefer supplied title over style based title
754  if (!title.isEmpty()) {
755  msgType = title;
756  }
757  else {
758  switch (style) {
760  msgType = tr("Error");
761  break;
763  msgType = tr("Warning");
764  break;
766  msgType = tr("Information");
767  break;
768  default:
769  break;
770  }
771  }
772  // Append title to "Bitcoin - "
773  if (!msgType.isEmpty())
774  strTitle += " - " + msgType;
775 
776  // Check for error/warning icon
777  if (style & CClientUIInterface::ICON_ERROR) {
778  nMBoxIcon = QMessageBox::Critical;
779  nNotifyIcon = Notificator::Critical;
780  }
781  else if (style & CClientUIInterface::ICON_WARNING) {
782  nMBoxIcon = QMessageBox::Warning;
783  nNotifyIcon = Notificator::Warning;
784  }
785 
786  // Display message
787  if (style & CClientUIInterface::MODAL) {
788  // Check for buttons, use OK as default, if none was supplied
789  QMessageBox::StandardButton buttons;
790  if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
791  buttons = QMessageBox::Ok;
792 
793  // Ensure we get users attention, but only if main window is visible
794  // as we don't want to pop up the main window for messages that happen before
795  // initialization is finished.
796  if(!(style & CClientUIInterface::NOSHOWGUI))
798  QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
799  int r = mBox.exec();
800  if (ret != NULL)
801  *ret = r == QMessageBox::Ok;
802  }
803  else
804  notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
805 }
806 
807 void BitcoinGUI::changeEvent(QEvent *e)
808 {
809  QMainWindow::changeEvent(e);
810 #ifndef Q_OS_MAC // Ignored on Mac
811  if(e->type() == QEvent::WindowStateChange)
812  {
814  {
815  QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
816  if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
817  {
818  QTimer::singleShot(0, this, SLOT(hide()));
819  e->ignore();
820  }
821  }
822  }
823 #endif
824 }
825 
826 void BitcoinGUI::closeEvent(QCloseEvent *event)
827 {
828  if(clientModel)
829  {
830 #ifndef Q_OS_MAC // Ignored on Mac
833  {
834  QApplication::quit();
835  }
836 #endif
837  }
838  QMainWindow::closeEvent(event);
839 }
840 
841 #ifdef ENABLE_WALLET
842 void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address)
843 {
844  // On new transaction, make an info balloon
845  message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
846  tr("Date: %1\n"
847  "Amount: %2\n"
848  "Type: %3\n"
849  "Address: %4\n")
850  .arg(date)
851  .arg(BitcoinUnits::formatWithUnit(unit, amount, true))
852  .arg(type)
853  .arg(address), CClientUIInterface::MSG_INFORMATION);
854 }
855 #endif
856 
857 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
858 {
859  // Accept only URIs
860  if(event->mimeData()->hasUrls())
861  event->acceptProposedAction();
862 }
863 
864 void BitcoinGUI::dropEvent(QDropEvent *event)
865 {
866  if(event->mimeData()->hasUrls())
867  {
868  foreach(const QUrl &uri, event->mimeData()->urls())
869  {
870  emit receivedURI(uri.toString());
871  }
872  }
873  event->acceptProposedAction();
874 }
875 
876 bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
877 {
878  // Catch status tip events
879  if (event->type() == QEvent::StatusTip)
880  {
881  // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
882  if (progressBarLabel->isVisible() || progressBar->isVisible())
883  return true;
884  }
885  return QMainWindow::eventFilter(object, event);
886 }
887 
888 #ifdef ENABLE_WALLET
889 bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
890 {
891  // URI has to be valid
892  if (walletFrame && walletFrame->handlePaymentRequest(recipient))
893  {
895  gotoSendCoinsPage();
896  return true;
897  }
898  else
899  return false;
900 }
901 
902 void BitcoinGUI::setEncryptionStatus(int status)
903 {
904  switch(status)
905  {
907  labelEncryptionIcon->hide();
908  encryptWalletAction->setChecked(false);
909  changePassphraseAction->setEnabled(false);
910  encryptWalletAction->setEnabled(true);
911  break;
913  labelEncryptionIcon->show();
914  labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
915  labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
916  encryptWalletAction->setChecked(true);
917  changePassphraseAction->setEnabled(true);
918  encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
919  break;
920  case WalletModel::Locked:
921  labelEncryptionIcon->show();
922  labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
923  labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
924  encryptWalletAction->setChecked(true);
925  changePassphraseAction->setEnabled(true);
926  encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
927  break;
928  }
929 }
930 #endif
931 
932 void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
933 {
934  // activateWindow() (sometimes) helps with keyboard focus on Windows
935  if (isHidden())
936  {
937  show();
938  activateWindow();
939  }
940  else if (isMinimized())
941  {
942  showNormal();
943  activateWindow();
944  }
945  else if (GUIUtil::isObscured(this))
946  {
947  raise();
948  activateWindow();
949  }
950  else if(fToggleHidden)
951  hide();
952 }
953 
955 {
956  showNormalIfMinimized(true);
957 }
958 
960 {
961  if (ShutdownRequested())
962  {
963  if(rpcConsole)
964  rpcConsole->hide();
965  qApp->quit();
966  }
967 }
968 
969 static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
970 {
971  bool modal = (style & CClientUIInterface::MODAL);
972  bool ret = false;
973  // In case of modal message, use blocking connection to wait for user to click a button
974  QMetaObject::invokeMethod(gui, "message",
975  modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
976  Q_ARG(QString, QString::fromStdString(caption)),
977  Q_ARG(QString, QString::fromStdString(message)),
978  Q_ARG(unsigned int, style),
979  Q_ARG(bool*, &ret));
980  return ret;
981 }
982 
984 {
985  // Connect signals to client
986  uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
987 }
988 
990 {
991  // Disconnect signals from client
992  uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
993 }
void subscribeToCoreSignals()
Connect core signals to GUI client.
Definition: bitcoingui.cpp:983
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
Definition: bitcoingui.cpp:989
CClientUIInterface uiInterface
Definition: util.cpp:100
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletframe.cpp:91
bool setCurrentWallet(const QString &name)
Definition: walletframe.cpp:62
bool getMinimizeOnClose()
Definition: optionsmodel.h:57
QAction * receiveCoinsAction
Definition: bitcoingui.h:88
Local Bitcoin RPC console.
Definition: rpcconsole.h:17
QMenuBar * appMenuBar
Definition: bitcoingui.h:77
static const QString DEFAULT_WALLET
Definition: bitcoingui.h:40
QAction * signMessageAction
Definition: bitcoingui.h:85
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
Value help(const Array &params, bool fHelp)
Definition: rpcserver.cpp:184
QAction * aboutAction
Definition: bitcoingui.h:87
void showNormalIfMinimized(bool fToggleHidden=false)
Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHid...
Definition: bitcoingui.cpp:932
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false)
Format as string (with unit)
void createTrayIcon(bool fIsTestnet)
Create system tray icon and notification.
Definition: bitcoingui.cpp:474
bool ShutdownRequested()
Definition: init.cpp:103
ClientModel * clientModel
Definition: bitcoingui.h:68
void createToolBars()
Create the toolbars.
Definition: bitcoingui.cpp:388
void createTrayIconMenu()
Create system tray menu (or setup the dock menu)
Definition: bitcoingui.cpp:496
RPCConsole * rpcConsole
Definition: bitcoingui.h:101
QAction * overviewAction
Definition: bitcoingui.h:78
static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string &message, const std::string &caption, unsigned int style)
Definition: bitcoingui.cpp:969
QAction * verifyMessageAction
Definition: bitcoingui.h:86
QAction * quitAction
Definition: bitcoingui.h:81
void dropEvent(QDropEvent *event)
Definition: bitcoingui.cpp:864
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:42
QAction * historyAction
Definition: bitcoingui.h:80
BitcoinGUI(bool fIsTestnet=false, QWidget *parent=0)
Definition: bitcoingui.cpp:60
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:339
void setWalletActionsEnabled(bool enabled)
Enable or disable all wallet-related actions.
Definition: bitcoingui.cpp:457
QAction * aboutQtAction
Definition: bitcoingui.h:94
OptionsModel * getOptionsModel()
Macintosh-specific dock icon handler.
Mask of all available buttons in CClientUIInterface::MessageBoxFlags This needs to be updated...
Definition: ui_interface.h:60
Bitcoin GUI main class.
Definition: bitcoingui.h:35
Don't bring GUI to foreground.
Definition: ui_interface.h:66
QLabel * progressBarLabel
Definition: bitcoingui.h:74
QSystemTrayIcon * trayIcon
Definition: bitcoingui.h:99
QAction * showHelpMessageAction
Definition: bitcoingui.h:97
Notify user of potential problem.
Definition: notificator.h:39
void removeAllWallets()
Definition: walletframe.cpp:83
QAction * backupWalletAction
Definition: bitcoingui.h:92
QLabel * labelConnectionsIcon
Definition: bitcoingui.h:72
void createActions(bool fIsTestnet)
Create the main UI actions.
Definition: bitcoingui.cpp:218
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
Save window size and position.
Definition: guiutil.cpp:732
Force blocking, modal message box dialog (not just OS notification)
Definition: ui_interface.h:64
void showOutOfSyncWarning(bool fShow)
void setIcon(const QIcon &icon)
void setClientModel(ClientModel *model)
Definition: rpcconsole.cpp:264
void gotoHistoryPage()
Switch to history (transactions) page.
QAction * usedReceivingAddressesAction
Definition: bitcoingui.h:84
void setClientModel(ClientModel *clientModel)
Set the client model.
Definition: bitcoingui.cpp:403
void gotoOverviewPage()
Switch to overview (home) page.
QAction * toggleHideAction
Definition: bitcoingui.h:90
double getVerificationProgress() const
Definition: clientmodel.cpp:87
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:519
static MacDockIconHandler * instance()
void setClientModel(ClientModel *clientModel)
Definition: walletframe.cpp:35
void setMainWindow(QMainWindow *window)
bool isObscured(QWidget *w)
Definition: guiutil.cpp:358
"About" dialog box
Definition: utilitydialog.h:20
void optionsClicked()
Show configuration dialog.
Definition: bitcoingui.cpp:544
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
void notify(Class cls, const QString &title, const QString &text, const QIcon &icon=QIcon(), int millisTimeout=10000)
Show notification message.
bool eventFilter(QObject *object, QEvent *event)
Definition: bitcoingui.cpp:876
QLabel * labelBlocksIcon
Definition: bitcoingui.h:73
bool addWallet(const QString &name, WalletModel *walletModel)
Definition: walletframe.cpp:40
QDateTime getLastBlockDate() const
Definition: clientmodel.cpp:78
BlockSource
Definition: clientmodel.h:21
WalletFrame * walletFrame
Definition: bitcoingui.h:69
QAction * usedSendingAddressesAction
Definition: bitcoingui.h:83
void setModel(OptionsModel *model)
QAction * openRPCConsoleAction
Definition: bitcoingui.h:95
void detectShutdown()
called by a timer to check if fRequestShutdown has been set
Definition: bitcoingui.cpp:959
Cross-platform desktop notification client.
Definition: notificator.h:24
Informational message.
Definition: notificator.h:38
void showHelpMessageClicked()
Show help message dialog.
Definition: bitcoingui.cpp:564
void dragEnterEvent(QDragEnterEvent *event)
Definition: bitcoingui.cpp:857
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
Restore window size and position.
Definition: guiutil.cpp:739
Notificator * notificator
Definition: bitcoingui.h:100
Model for Bitcoin network client.
Definition: clientmodel.h:36
An error occurred.
Definition: notificator.h:40
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
QAction * sendCoinsAction
Definition: bitcoingui.h:82
int getNumBlocks() const
Definition: clientmodel.cpp:56
static const int STATUSBAR_ICONSIZE
Definition: guiconstants.h:15
QAction * openAction
Definition: bitcoingui.h:96
void trayIconActivated(QSystemTrayIcon::ActivationReason reason)
Handle tray icon clicked.
Definition: bitcoingui.cpp:534
QAction * changePassphraseAction
Definition: bitcoingui.h:93
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
void gotoReceiveCoinsPage()
Switch to receive coins page.
void closeEvent(QCloseEvent *event)
Definition: bitcoingui.cpp:826
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:96
QAction * balancesAction
Definition: bitcoingui.h:79
void changeEvent(QEvent *e)
Definition: bitcoingui.cpp:807
int prevBlocks
Keep track of previous number of blocks, to detect progress.
Definition: bitcoingui.h:104
void toggleHidden()
Simply calls showNormalIfMinimized(true) for use in SLOT() macro.
Definition: bitcoingui.cpp:954
int spinnerFrame
Definition: bitcoingui.h:105
QProgressBar * progressBar
Definition: bitcoingui.h:75
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Show message box.
Definition: ui_interface.h:75
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: bitcoingui.cpp:622
"Help message" dialog box
Definition: utilitydialog.h:38
void gotoBalancesPage()
Switch to balances page.
Preferences dialog.
Definition: optionsdialog.h:19
QAction * optionsAction
Definition: bitcoingui.h:89
QAction * encryptWalletAction
Definition: bitcoingui.h:91
void aboutClicked()
Show about dialog.
Definition: bitcoingui.cpp:554
void message(const QString &title, const QString &message, unsigned int style, bool *ret=NULL)
Notify the user of an event from the core network or transaction handling code.
Definition: bitcoingui.cpp:744
bool getMinimizeToTray()
Definition: optionsmodel.h:56
QLabel * labelEncryptionIcon
Definition: bitcoingui.h:71
enum BlockSource getBlockSource() const
Return true if core is importing blocks.
void createMenuBar()
Create the menu bar and sub-menus.
Definition: bitcoingui.cpp:343
Predefined combinations for certain default usage cases.
Definition: ui_interface.h:69
void setNumBlocks(int count)
Set number of blocks shown in the UI.
Definition: bitcoingui.cpp:637
#define SPINNER_FRAMES
Definition: guiconstants.h:42
void setModel(ClientModel *model)