]>
Commit | Line | Data |
---|---|---|
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 |
58 | const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; |
59 | ||
80fccb0e | 60 | BitcoinGUI::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 | 204 | BitcoinGUI::~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 | 218 | void 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 | 334 | void 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 | ||
379 | void 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 | 393 | void 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 | 423 | bool 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 | ||
431 | bool BitcoinGUI::setCurrentWallet(const QString& name) | |
432 | { | |
b7f4b6d3 WL |
433 | if(!walletFrame) |
434 | return false; | |
67155d92 EL |
435 | return walletFrame->setCurrentWallet(name); |
436 | } | |
437 | ||
438 | void 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 |
447 | void 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 | 463 | void 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 | ||
485 | void 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 |
523 | void 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 |
533 | void 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 | 543 | void 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 |
553 | void 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 |
561 | void 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 |
570 | void BitcoinGUI::gotoOverviewPage() |
571 | { | |
16314593 | 572 | overviewAction->setChecked(true); |
67155d92 EL |
573 | if (walletFrame) walletFrame->gotoOverviewPage(); |
574 | } | |
575 | ||
576 | void BitcoinGUI::gotoHistoryPage() | |
577 | { | |
16314593 | 578 | historyAction->setChecked(true); |
67155d92 EL |
579 | if (walletFrame) walletFrame->gotoHistoryPage(); |
580 | } | |
581 | ||
67155d92 EL |
582 | void BitcoinGUI::gotoReceiveCoinsPage() |
583 | { | |
16314593 | 584 | receiveCoinsAction->setChecked(true); |
67155d92 EL |
585 | if (walletFrame) walletFrame->gotoReceiveCoinsPage(); |
586 | } | |
587 | ||
abf11f79 | 588 | void BitcoinGUI::gotoSendCoinsPage(QString addr) |
67155d92 | 589 | { |
16314593 | 590 | sendCoinsAction->setChecked(true); |
abf11f79 | 591 | if (walletFrame) walletFrame->gotoSendCoinsPage(addr); |
67155d92 EL |
592 | } |
593 | ||
594 | void BitcoinGUI::gotoSignMessageTab(QString addr) | |
595 | { | |
596 | if (walletFrame) walletFrame->gotoSignMessageTab(addr); | |
597 | } | |
598 | ||
599 | void BitcoinGUI::gotoVerifyMessageTab(QString addr) | |
600 | { | |
0dcf9e53 | 601 | if (walletFrame) walletFrame->gotoVerifyMessageTab(addr); |
67155d92 | 602 | } |
b7f4b6d3 | 603 | #endif |
67155d92 | 604 | |
1a6d504a WL |
605 | void 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 | 620 | void 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 | 734 | void 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 | |
797 | void 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 | ||
816 | void 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 | 832 | void 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 |
847 | void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) |
848 | { | |
fa2544e7 | 849 | // Accept only URIs |
db7f0234 WL |
850 | if(event->mimeData()->hasUrls()) |
851 | event->acceptProposedAction(); | |
852 | } | |
853 | ||
854 | void 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 |
866 | bool 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 | 879 | bool 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 |
892 | void 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 | 922 | void 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 | ||
944 | void BitcoinGUI::toggleHidden() | |
945 | { | |
946 | showNormalIfMinimized(true); | |
17690ea5 | 947 | } |
723035bb GA |
948 | |
949 | void BitcoinGUI::detectShutdown() | |
950 | { | |
951 | if (ShutdownRequested()) | |
9a2305a1 WL |
952 | { |
953 | if(rpcConsole) | |
954 | rpcConsole->hide(); | |
955 | qApp->quit(); | |
956 | } | |
723035bb | 957 | } |
35ecf854 WL |
958 | |
959 | static 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 | ||
973 | void BitcoinGUI::subscribeToCoreSignals() | |
974 | { | |
975 | // Connect signals to client | |
976 | uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); | |
977 | } | |
978 | ||
979 | void BitcoinGUI::unsubscribeFromCoreSignals() | |
980 | { | |
981 | // Disconnect signals from client | |
982 | uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); | |
983 | } |