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.

starwelsgui.cpp 44KB

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