]> Git Repo - VerusCoin.git/blob - src/qt/bitcoingui.cpp
Copyright header updates s/2013/2014 on files whose last git commit was done in 2014.
[VerusCoin.git] / src / qt / bitcoingui.cpp
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("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
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     {
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     }
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->setMinimumWidth(56);
155     frameBlocks->setMaximumWidth(56);
156     QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
157     frameBlocksLayout->setContentsMargins(3,0,3,0);
158     frameBlocksLayout->setSpacing(3);
159     labelEncryptionIcon = new QLabel();
160     labelConnectionsIcon = new QLabel();
161     labelBlocksIcon = new QLabel();
162     frameBlocksLayout->addStretch();
163     frameBlocksLayout->addWidget(labelEncryptionIcon);
164     frameBlocksLayout->addStretch();
165     frameBlocksLayout->addWidget(labelConnectionsIcon);
166     frameBlocksLayout->addStretch();
167     frameBlocksLayout->addWidget(labelBlocksIcon);
168     frameBlocksLayout->addStretch();
169
170     // Progress bar and label for blocks download
171     progressBarLabel = new QLabel();
172     progressBarLabel->setVisible(false);
173     progressBar = new QProgressBar();
174     progressBar->setAlignment(Qt::AlignCenter);
175     progressBar->setVisible(false);
176
177     // Override style sheet for progress bar for styles that have a segmented progress bar,
178     // as they make the text unreadable (workaround for issue #1071)
179     // See https://qt-project.org/doc/qt-4.8/gallery.html
180     QString curStyle = QApplication::style()->metaObject()->className();
181     if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
182     {
183         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; }");
184     }
185
186     statusBar()->addWidget(progressBarLabel);
187     statusBar()->addWidget(progressBar);
188     statusBar()->addPermanentWidget(frameBlocks);
189
190     connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
191
192     // prevents an oben debug window from becoming stuck/unusable on client shutdown
193     connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
194
195     // Install event filter to be able to catch status tip events (QEvent::StatusTip)
196     this->installEventFilter(this);
197
198     // Initially wallet actions should be disabled
199     setWalletActionsEnabled(false);
200
201     // Subscribe to notifications from core
202     subscribeToCoreSignals();
203 }
204
205 BitcoinGUI::~BitcoinGUI()
206 {
207     // Unsubscribe from notifications from core
208     unsubscribeFromCoreSignals();
209
210     GUIUtil::saveWindowGeometry("nWindow", this);
211     if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
212         trayIcon->hide();
213 #ifdef Q_OS_MAC
214     delete appMenuBar;
215     MacDockIconHandler::instance()->setMainWindow(NULL);
216 #endif
217 }
218
219 void BitcoinGUI::createActions(bool fIsTestnet)
220 {
221     QActionGroup *tabGroup = new QActionGroup(this);
222
223     overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
224     overviewAction->setStatusTip(tr("Show general overview of wallet"));
225     overviewAction->setToolTip(overviewAction->statusTip());
226     overviewAction->setCheckable(true);
227     overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
228     tabGroup->addAction(overviewAction);
229
230     sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this);
231     sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
232     sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
233     sendCoinsAction->setCheckable(true);
234     sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
235     tabGroup->addAction(sendCoinsAction);
236
237     receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
238     receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
239     receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
240     receiveCoinsAction->setCheckable(true);
241     receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
242     tabGroup->addAction(receiveCoinsAction);
243
244     historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
245     historyAction->setStatusTip(tr("Browse transaction history"));
246     historyAction->setToolTip(historyAction->statusTip());
247     historyAction->setCheckable(true);
248     historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
249     tabGroup->addAction(historyAction);
250
251     // These showNormalIfMinimized are needed because Send Coins and Receive Coins
252     // can be triggered from the tray menu, and need to show the GUI to be useful.
253     connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
254     connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
255     connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
256     connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
257     connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
258     connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
259     connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
260     connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
261
262     quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
263     quitAction->setStatusTip(tr("Quit application"));
264     quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
265     quitAction->setMenuRole(QAction::QuitRole);
266     if (!fIsTestnet)
267         aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin Core"), this);
268     else
269         aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin Core"), this);
270     aboutAction->setStatusTip(tr("Show information about Bitcoin"));
271     aboutAction->setMenuRole(QAction::AboutRole);
272 #if QT_VERSION < 0x050000
273     aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
274 #else
275     aboutQtAction = new QAction(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
276 #endif
277     aboutQtAction->setStatusTip(tr("Show information about Qt"));
278     aboutQtAction->setMenuRole(QAction::AboutQtRole);
279     optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
280     optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin"));
281     optionsAction->setMenuRole(QAction::PreferencesRole);
282     if (!fIsTestnet)
283         toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
284     else
285         toggleHideAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&Show / Hide"), this);
286     toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
287
288     encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
289     encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
290     encryptWalletAction->setCheckable(true);
291     backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
292     backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
293     changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
294     changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
295     signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
296     signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
297     verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
298     verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
299
300     openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this);
301     openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
302
303     usedSendingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
304     usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
305     usedReceivingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
306     usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
307
308     openAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_FileIcon), tr("Open &URI..."), this);
309     openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
310
311     showHelpMessageAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Command-line options"), this);
312     showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options"));
313
314     connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
315     connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
316     connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
317     connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
318     connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
319     connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
320 #ifdef ENABLE_WALLET
321     if(walletFrame)
322     {
323         connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
324         connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
325         connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
326         connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
327         connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
328         connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
329         connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
330         connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
331     }
332 #endif
333 }
334
335 void BitcoinGUI::createMenuBar()
336 {
337 #ifdef Q_OS_MAC
338     // Create a decoupled menu bar on Mac which stays even if the window is closed
339     appMenuBar = new QMenuBar();
340 #else
341     // Get the main window's menu bar on other platforms
342     appMenuBar = menuBar();
343 #endif
344
345     // Configure the menus
346     QMenu *file = appMenuBar->addMenu(tr("&File"));
347     if(walletFrame)
348     {
349         file->addAction(openAction);
350         file->addAction(backupWalletAction);
351         file->addAction(signMessageAction);
352         file->addAction(verifyMessageAction);
353         file->addSeparator();
354         file->addAction(usedSendingAddressesAction);
355         file->addAction(usedReceivingAddressesAction);
356         file->addSeparator();
357     }
358     file->addAction(quitAction);
359
360     QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
361     if(walletFrame)
362     {
363         settings->addAction(encryptWalletAction);
364         settings->addAction(changePassphraseAction);
365         settings->addSeparator();
366     }
367     settings->addAction(optionsAction);
368
369     QMenu *help = appMenuBar->addMenu(tr("&Help"));
370     if(walletFrame)
371     {
372         help->addAction(openRPCConsoleAction);
373     }
374     help->addAction(showHelpMessageAction);
375     help->addSeparator();
376     help->addAction(aboutAction);
377     help->addAction(aboutQtAction);
378 }
379
380 void BitcoinGUI::createToolBars()
381 {
382     if(walletFrame)
383     {
384         QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
385         toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
386         toolbar->addAction(overviewAction);
387         toolbar->addAction(sendCoinsAction);
388         toolbar->addAction(receiveCoinsAction);
389         toolbar->addAction(historyAction);
390         overviewAction->setChecked(true);
391     }
392 }
393
394 void BitcoinGUI::setClientModel(ClientModel *clientModel)
395 {
396     this->clientModel = clientModel;
397     if(clientModel)
398     {
399         // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
400         // while the client has not yet fully loaded
401         createTrayIconMenu();
402
403         // Keep up to date with client
404         setNumConnections(clientModel->getNumConnections());
405         connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
406
407         setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
408         connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
409
410         // Receive and report messages from client model
411         connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
412
413         rpcConsole->setClientModel(clientModel);
414 #ifdef ENABLE_WALLET
415         if(walletFrame)
416         {
417             walletFrame->setClientModel(clientModel);
418         }
419 #endif
420     }
421 }
422
423 #ifdef ENABLE_WALLET
424 bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
425 {
426     if(!walletFrame)
427         return false;
428     setWalletActionsEnabled(true);
429     return walletFrame->addWallet(name, walletModel);
430 }
431
432 bool BitcoinGUI::setCurrentWallet(const QString& name)
433 {
434     if(!walletFrame)
435         return false;
436     return walletFrame->setCurrentWallet(name);
437 }
438
439 void BitcoinGUI::removeAllWallets()
440 {
441     if(!walletFrame)
442         return;
443     setWalletActionsEnabled(false);
444     walletFrame->removeAllWallets();
445 }
446 #endif
447
448 void BitcoinGUI::setWalletActionsEnabled(bool enabled)
449 {
450     overviewAction->setEnabled(enabled);
451     sendCoinsAction->setEnabled(enabled);
452     receiveCoinsAction->setEnabled(enabled);
453     historyAction->setEnabled(enabled);
454     encryptWalletAction->setEnabled(enabled);
455     backupWalletAction->setEnabled(enabled);
456     changePassphraseAction->setEnabled(enabled);
457     signMessageAction->setEnabled(enabled);
458     verifyMessageAction->setEnabled(enabled);
459     usedSendingAddressesAction->setEnabled(enabled);
460     usedReceivingAddressesAction->setEnabled(enabled);
461     openAction->setEnabled(enabled);
462 }
463
464 void BitcoinGUI::createTrayIcon(bool fIsTestnet)
465 {
466 #ifndef Q_OS_MAC
467     trayIcon = new QSystemTrayIcon(this);
468
469     if (!fIsTestnet)
470     {
471         trayIcon->setToolTip(tr("Bitcoin client"));
472         trayIcon->setIcon(QIcon(":/icons/toolbar"));
473     }
474     else
475     {
476         trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]"));
477         trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
478     }
479
480     trayIcon->show();
481 #endif
482
483     notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
484 }
485
486 void BitcoinGUI::createTrayIconMenu()
487 {
488     QMenu *trayIconMenu;
489 #ifndef Q_OS_MAC
490     // return if trayIcon is unset (only on non-Mac OSes)
491     if (!trayIcon)
492         return;
493
494     trayIconMenu = new QMenu(this);
495     trayIcon->setContextMenu(trayIconMenu);
496
497     connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
498             this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
499 #else
500     // Note: On Mac, the dock icon is used to provide the tray's functionality.
501     MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
502     dockIconHandler->setMainWindow((QMainWindow *)this);
503     trayIconMenu = dockIconHandler->dockMenu();
504 #endif
505
506     // Configuration of the tray icon (or dock icon) icon menu
507     trayIconMenu->addAction(toggleHideAction);
508     trayIconMenu->addSeparator();
509     trayIconMenu->addAction(sendCoinsAction);
510     trayIconMenu->addAction(receiveCoinsAction);
511     trayIconMenu->addSeparator();
512     trayIconMenu->addAction(signMessageAction);
513     trayIconMenu->addAction(verifyMessageAction);
514     trayIconMenu->addSeparator();
515     trayIconMenu->addAction(optionsAction);
516     trayIconMenu->addAction(openRPCConsoleAction);
517 #ifndef Q_OS_MAC // This is built-in on Mac
518     trayIconMenu->addSeparator();
519     trayIconMenu->addAction(quitAction);
520 #endif
521 }
522
523 #ifndef Q_OS_MAC
524 void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
525 {
526     if(reason == QSystemTrayIcon::Trigger)
527     {
528         // Click on system tray icon triggers show/hide of the main window
529         toggleHideAction->trigger();
530     }
531 }
532 #endif
533
534 void BitcoinGUI::optionsClicked()
535 {
536     if(!clientModel || !clientModel->getOptionsModel())
537         return;
538
539     OptionsDialog dlg(this);
540     dlg.setModel(clientModel->getOptionsModel());
541     dlg.exec();
542 }
543
544 void BitcoinGUI::aboutClicked()
545 {
546     if(!clientModel)
547         return;
548
549     AboutDialog dlg(this);
550     dlg.setModel(clientModel);
551     dlg.exec();
552 }
553
554 void BitcoinGUI::showHelpMessageClicked()
555 {
556     HelpMessageDialog *help = new HelpMessageDialog(this);
557     help->setAttribute(Qt::WA_DeleteOnClose);
558     help->show();
559 }
560
561 #ifdef ENABLE_WALLET
562 void BitcoinGUI::openClicked()
563 {
564     OpenURIDialog dlg(this);
565     if(dlg.exec())
566     {
567         emit receivedURI(dlg.getURI());
568     }
569 }
570
571 void BitcoinGUI::gotoOverviewPage()
572 {
573     overviewAction->setChecked(true);
574     if (walletFrame) walletFrame->gotoOverviewPage();
575 }
576
577 void BitcoinGUI::gotoHistoryPage()
578 {
579     historyAction->setChecked(true);
580     if (walletFrame) walletFrame->gotoHistoryPage();
581 }
582
583 void BitcoinGUI::gotoReceiveCoinsPage()
584 {
585     receiveCoinsAction->setChecked(true);
586     if (walletFrame) walletFrame->gotoReceiveCoinsPage();
587 }
588
589 void BitcoinGUI::gotoSendCoinsPage(QString addr)
590 {
591     sendCoinsAction->setChecked(true);
592     if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
593 }
594
595 void BitcoinGUI::gotoSignMessageTab(QString addr)
596 {
597     if (walletFrame) walletFrame->gotoSignMessageTab(addr);
598 }
599
600 void BitcoinGUI::gotoVerifyMessageTab(QString addr)
601 {
602     if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
603 }
604 #endif
605
606 void BitcoinGUI::setNumConnections(int count)
607 {
608     QString icon;
609     switch(count)
610     {
611     case 0: icon = ":/icons/connect_0"; break;
612     case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
613     case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
614     case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
615     default: icon = ":/icons/connect_4"; break;
616     }
617     labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
618     labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
619 }
620
621 void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
622 {
623     // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text)
624     statusBar()->clearMessage();
625
626     // Acquire current block source
627     enum BlockSource blockSource = clientModel->getBlockSource();
628     switch (blockSource) {
629         case BLOCK_SOURCE_NETWORK:
630             progressBarLabel->setText(tr("Synchronizing with network..."));
631             break;
632         case BLOCK_SOURCE_DISK:
633             progressBarLabel->setText(tr("Importing blocks from disk..."));
634             break;
635         case BLOCK_SOURCE_REINDEX:
636             progressBarLabel->setText(tr("Reindexing blocks on disk..."));
637             break;
638         case BLOCK_SOURCE_NONE:
639             // Case: not Importing, not Reindexing and no network connection
640             progressBarLabel->setText(tr("No block source available..."));
641             break;
642     }
643
644     QString tooltip;
645
646     QDateTime lastBlockDate = clientModel->getLastBlockDate();
647     QDateTime currentDate = QDateTime::currentDateTime();
648     int secs = lastBlockDate.secsTo(currentDate);
649
650     if(count < nTotalBlocks)
651     {
652         tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks);
653     }
654     else
655     {
656         tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
657     }
658
659     // Set icon state: spinning if catching up, tick otherwise
660     if(secs < 90*60 && count >= nTotalBlocks)
661     {
662         tooltip = tr("Up to date") + QString(".<br>") + tooltip;
663         labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
664
665 #ifdef ENABLE_WALLET
666         if(walletFrame)
667             walletFrame->showOutOfSyncWarning(false);
668 #endif
669
670         progressBarLabel->setVisible(false);
671         progressBar->setVisible(false);
672     }
673     else
674     {
675         // Represent time from last generated block in human readable text
676         QString timeBehindText;
677         if(secs < 48*60*60)
678         {
679             timeBehindText = tr("%n hour(s)","",secs/(60*60));
680         }
681         else if(secs < 14*24*60*60)
682         {
683             timeBehindText = tr("%n day(s)","",secs/(24*60*60));
684         }
685         else
686         {
687             timeBehindText = tr("%n week(s)","",secs/(7*24*60*60));
688         }
689
690         progressBarLabel->setVisible(true);
691         progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
692         progressBar->setMaximum(1000000000);
693         progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5);
694         progressBar->setVisible(true);
695
696         tooltip = tr("Catching up...") + QString("<br>") + tooltip;
697         if(count != prevBlocks)
698         {
699             labelBlocksIcon->setPixmap(QIcon(QString(
700                 ":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')))
701                 .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
702             spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
703         }
704         prevBlocks = count;
705
706 #ifdef ENABLE_WALLET
707         if(walletFrame)
708             walletFrame->showOutOfSyncWarning(true);
709 #endif
710
711         tooltip += QString("<br>");
712         tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
713         tooltip += QString("<br>");
714         tooltip += tr("Transactions after this will not yet be visible.");
715     }
716
717     // Don't word-wrap this (fixed-width) tooltip
718     tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
719
720     labelBlocksIcon->setToolTip(tooltip);
721     progressBarLabel->setToolTip(tooltip);
722     progressBar->setToolTip(tooltip);
723 }
724
725 void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
726 {
727     QString strTitle = tr("Bitcoin"); // default title
728     // Default to information icon
729     int nMBoxIcon = QMessageBox::Information;
730     int nNotifyIcon = Notificator::Information;
731
732     QString msgType;
733
734     // Prefer supplied title over style based title
735     if (!title.isEmpty()) {
736         msgType = title;
737     }
738     else {
739         switch (style) {
740         case CClientUIInterface::MSG_ERROR:
741             msgType = tr("Error");
742             break;
743         case CClientUIInterface::MSG_WARNING:
744             msgType = tr("Warning");
745             break;
746         case CClientUIInterface::MSG_INFORMATION:
747             msgType = tr("Information");
748             break;
749         default:
750             break;
751         }
752     }
753     // Append title to "Bitcoin - "
754     if (!msgType.isEmpty())
755         strTitle += " - " + msgType;
756
757     // Check for error/warning icon
758     if (style & CClientUIInterface::ICON_ERROR) {
759         nMBoxIcon = QMessageBox::Critical;
760         nNotifyIcon = Notificator::Critical;
761     }
762     else if (style & CClientUIInterface::ICON_WARNING) {
763         nMBoxIcon = QMessageBox::Warning;
764         nNotifyIcon = Notificator::Warning;
765     }
766
767     // Display message
768     if (style & CClientUIInterface::MODAL) {
769         // Check for buttons, use OK as default, if none was supplied
770         QMessageBox::StandardButton buttons;
771         if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
772             buttons = QMessageBox::Ok;
773
774         // Ensure we get users attention, but only if main window is visible
775         // as we don't want to pop up the main window for messages that happen before
776         // initialization is finished.
777         if(!(style & CClientUIInterface::NOSHOWGUI))
778             showNormalIfMinimized();
779         QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
780         int r = mBox.exec();
781         if (ret != NULL)
782             *ret = r == QMessageBox::Ok;
783     }
784     else
785         notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
786 }
787
788 void BitcoinGUI::changeEvent(QEvent *e)
789 {
790     QMainWindow::changeEvent(e);
791 #ifndef Q_OS_MAC // Ignored on Mac
792     if(e->type() == QEvent::WindowStateChange)
793     {
794         if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray())
795         {
796             QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
797             if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
798             {
799                 QTimer::singleShot(0, this, SLOT(hide()));
800                 e->ignore();
801             }
802         }
803     }
804 #endif
805 }
806
807 void BitcoinGUI::closeEvent(QCloseEvent *event)
808 {
809     if(clientModel)
810     {
811 #ifndef Q_OS_MAC // Ignored on Mac
812         if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
813            !clientModel->getOptionsModel()->getMinimizeOnClose())
814         {
815             QApplication::quit();
816         }
817 #endif
818     }
819     QMainWindow::closeEvent(event);
820 }
821
822 #ifdef ENABLE_WALLET
823 void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address)
824 {
825     // On new transaction, make an info balloon
826     message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
827              tr("Date: %1\n"
828                 "Amount: %2\n"
829                 "Type: %3\n"
830                 "Address: %4\n")
831                   .arg(date)
832                   .arg(BitcoinUnits::formatWithUnit(unit, amount, true))
833                   .arg(type)
834                   .arg(address), CClientUIInterface::MSG_INFORMATION);
835 }
836 #endif
837
838 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
839 {
840     // Accept only URIs
841     if(event->mimeData()->hasUrls())
842         event->acceptProposedAction();
843 }
844
845 void BitcoinGUI::dropEvent(QDropEvent *event)
846 {
847     if(event->mimeData()->hasUrls())
848     {
849         foreach(const QUrl &uri, event->mimeData()->urls())
850         {
851             emit receivedURI(uri.toString());
852         }
853     }
854     event->acceptProposedAction();
855 }
856
857 bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
858 {
859     // Catch status tip events
860     if (event->type() == QEvent::StatusTip)
861     {
862         // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
863         if (progressBarLabel->isVisible() || progressBar->isVisible())
864             return true;
865     }
866     return QMainWindow::eventFilter(object, event);
867 }
868
869 #ifdef ENABLE_WALLET
870 bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
871 {
872     // URI has to be valid
873     if (walletFrame && walletFrame->handlePaymentRequest(recipient))
874     {
875         showNormalIfMinimized();
876         gotoSendCoinsPage();
877         return true;
878     }
879     else
880         return false;
881 }
882
883 void BitcoinGUI::setEncryptionStatus(int status)
884 {
885     switch(status)
886     {
887     case WalletModel::Unencrypted:
888         labelEncryptionIcon->hide();
889         encryptWalletAction->setChecked(false);
890         changePassphraseAction->setEnabled(false);
891         encryptWalletAction->setEnabled(true);
892         break;
893     case WalletModel::Unlocked:
894         labelEncryptionIcon->show();
895         labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
896         labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
897         encryptWalletAction->setChecked(true);
898         changePassphraseAction->setEnabled(true);
899         encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
900         break;
901     case WalletModel::Locked:
902         labelEncryptionIcon->show();
903         labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
904         labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
905         encryptWalletAction->setChecked(true);
906         changePassphraseAction->setEnabled(true);
907         encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
908         break;
909     }
910 }
911 #endif
912
913 void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
914 {
915     // activateWindow() (sometimes) helps with keyboard focus on Windows
916     if (isHidden())
917     {
918         show();
919         activateWindow();
920     }
921     else if (isMinimized())
922     {
923         showNormal();
924         activateWindow();
925     }
926     else if (GUIUtil::isObscured(this))
927     {
928         raise();
929         activateWindow();
930     }
931     else if(fToggleHidden)
932         hide();
933 }
934
935 void BitcoinGUI::toggleHidden()
936 {
937     showNormalIfMinimized(true);
938 }
939
940 void BitcoinGUI::detectShutdown()
941 {
942     if (ShutdownRequested())
943     {
944         if(rpcConsole)
945             rpcConsole->hide();
946         qApp->quit();
947     }
948 }
949
950 static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
951 {
952     bool modal = (style & CClientUIInterface::MODAL);
953     bool ret = false;
954     // In case of modal message, use blocking connection to wait for user to click a button
955     QMetaObject::invokeMethod(gui, "message",
956                                modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
957                                Q_ARG(QString, QString::fromStdString(caption)),
958                                Q_ARG(QString, QString::fromStdString(message)),
959                                Q_ARG(unsigned int, style),
960                                Q_ARG(bool*, &ret));
961     return ret;
962 }
963
964 void BitcoinGUI::subscribeToCoreSignals()
965 {
966     // Connect signals to client
967     uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
968 }
969
970 void BitcoinGUI::unsubscribeFromCoreSignals()
971 {
972     // Disconnect signals from client
973     uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
974 }
This page took 0.085235 seconds and 4 git commands to generate.