You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitcoingui.cpp 42KB

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