// Qt bitcoin GUI. // // Copyright (c) 2011-2012 W.J. van der Laan // Copyright (c) 2011-2012 The Bitcoin Developers // Copyright (c) 2017-2018 The Gostcoin Developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // // I2P-patch // Copyright (c) 2012-2013 giv // #include #include "bitcoingui.h" #include "transactiontablemodel.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" #include "walletmodel.h" #include "walletframe.h" #include "optionsmodel.h" #include "transactiondescdialog.h" #include "bitcoinunits.h" #include "guiconstants.h" #include "notificator.h" #include "guiutil.h" #include "rpcconsole.h" #include "ui_interface.h" #include "wallet.h" #include "init.h" #include "showi2paddresses.h" #ifdef Q_OS_MAC #include "macdockiconhandler.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #endif #include #include #include #include #include #include const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; BitcoinGUI::BitcoinGUI(QWidget *parent) : QMainWindow(parent), clientModel(0), encryptWalletAction(0), changePassphraseAction(0), aboutQtAction(0), trayIcon(0), notificator(0), rpcConsole(0), prevBlocks(0) { restoreWindowGeometry(); setWindowTitle(tr("Gostcoin") + " - " + tr("Wallet")); #ifndef Q_OS_MAC QApplication::setWindowIcon(QIcon(":icons/gostcoin")); setWindowIcon(QIcon(":icons/gostcoin")); #else setUnifiedTitleAndToolBarOnMac(true); QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif // Create wallet frame and make it the central widget walletFrame = new WalletFrame(this); setCentralWidget(walletFrame); // Accept D&D of URIs setAcceptDrops(true); // Create actions for the toolbar, menu bar and tray/dock icon // Needs walletFrame to be initialized createActions(); // Create application menu bar createMenuBar(); // Create the toolbars createToolBars(); // Create status bar statusBar(); // Status bar notification icons QFrame *frameBlocks = new QFrame(); frameBlocks->setContentsMargins(0,0,0,0); frameBlocks->setMinimumWidth(56); //frameBlocks->setMaximumWidth(56); QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks); frameBlocksLayout->setContentsMargins(3,0,3,0); frameBlocksLayout->setSpacing(3); labelEncryptionIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); labelI2PConnections = new QLabel(); labelI2POnly = new QLabel(); labelI2PGenerated = new QLabel(); frameBlocksLayout->addWidget(labelEncryptionIcon); frameBlocksLayout->addWidget(labelI2PGenerated); frameBlocksLayout->addWidget(labelI2POnly); frameBlocksLayout->addWidget(labelI2PConnections); frameBlocksLayout->addWidget(labelConnectionsIcon); frameBlocksLayout->addWidget(labelBlocksIcon); // Progress bar and label for blocks download progressBarLabel = new QLabel(); progressBarLabel->setVisible(false); progressBar = new QProgressBar(); progressBar->setAlignment(Qt::AlignCenter); progressBar->setVisible(false); // Override style sheet for progress bar for styles that have a segmented progress bar, // as they make the text unreadable (workaround for issue #1071) // See https://qt-project.org/doc/qt-4.8/gallery.html QString curStyle = QApplication::style()->metaObject()->className(); if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle") { 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; }"); } statusBar()->addWidget(progressBarLabel); statusBar()->addWidget(progressBar); statusBar()->addPermanentWidget(frameBlocks); syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this); rpcConsole = new RPCConsole(this); connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); // Install event filter to be able to catch status tip events (QEvent::StatusTip) this->installEventFilter(this); // Initially wallet actions should be disabled setWalletActionsEnabled(false); } BitcoinGUI::~BitcoinGUI() { saveWindowGeometry(); if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) trayIcon->hide(); #ifdef Q_OS_MAC delete appMenuBar; MacDockIconHandler::instance()->setMainWindow(NULL); #endif } void BitcoinGUI::createActions() { QActionGroup *tabGroup = new QActionGroup(this); overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this); overviewAction->setStatusTip(tr("Show general overview of wallet")); overviewAction->setToolTip(overviewAction->statusTip()); overviewAction->setCheckable(true); overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); tabGroup->addAction(overviewAction); sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this); sendCoinsAction->setStatusTip(tr("Send coins to a Gostcoin address")); sendCoinsAction->setToolTip(sendCoinsAction->statusTip()); sendCoinsAction->setCheckable(true); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive"), this); receiveCoinsAction->setStatusTip(tr("Show the list of addresses for receiving payments")); receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip()); receiveCoinsAction->setCheckable(true); receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); tabGroup->addAction(receiveCoinsAction); historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setToolTip(historyAction->statusTip()); historyAction->setCheckable(true); historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(historyAction); addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Addresses"), this); addressBookAction->setStatusTip(tr("Edit the list of stored addresses and labels")); addressBookAction->setToolTip(addressBookAction->statusTip()); addressBookAction->setCheckable(true); addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); tabGroup->addAction(addressBookAction); connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setStatusTip(tr("Quit application")); quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); quitAction->setMenuRole(QAction::QuitRole); aboutAction = new QAction(QIcon(":/icons/gostcoin"), tr("&About Gostcoin"), this); aboutAction->setStatusTip(tr("Show information about Gostcoin")); aboutAction->setMenuRole(QAction::AboutRole); aboutQtAction = new QAction(QIcon(":/icons/qtlogo"), tr("About &Qt"), this); aboutQtAction->setStatusTip(tr("Show information about Qt")); aboutQtAction->setMenuRole(QAction::AboutQtRole); optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); optionsAction->setStatusTip(tr("Modify configuration options for Gostcoin")); optionsAction->setMenuRole(QAction::PreferencesRole); toggleHideAction = new QAction(QIcon(":/icons/gostcoin"), tr("&Show / Hide"), this); toggleHideAction->setStatusTip(tr("Show or hide the main Window")); encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this); encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet")); encryptWalletAction->setCheckable(true); backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this); backupWalletAction->setStatusTip(tr("Backup wallet to another location")); changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this); changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption")); signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this); signMessageAction->setStatusTip(tr("Sign messages with your Gostcoin addresses to prove you own them")); verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Gostcoin addresses")); openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked())); connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden())); connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool))); connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase())); connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab())); #ifdef USE_QRCODE printPaperWalletAction = new QAction(QIcon(":/icons/cash"), tr("&Print paper wallet..."), this); printPaperWalletAction->setIconVisibleInMenu(true); printPaperWalletAction->setStatusTip(tr("Generate new address and print")); connect(printPaperWalletAction, SIGNAL(triggered()), walletFrame, SLOT(printPaperWallet())); #endif } void BitcoinGUI::createMenuBar() { #ifdef Q_OS_MAC // Create a decoupled menu bar on Mac which stays even if the window is closed appMenuBar = new QMenuBar(); #else // Get the main window's menu bar on other platforms appMenuBar = menuBar(); #endif // Configure the menus QMenu *file = appMenuBar->addMenu(tr("&File")); file->addAction(backupWalletAction); file->addAction(signMessageAction); file->addAction(verifyMessageAction); file->addSeparator(); #ifdef USE_QRCODE file->addAction(printPaperWalletAction); file->addSeparator(); #endif file->addAction(quitAction); QMenu *settings = appMenuBar->addMenu(tr("&Settings")); settings->addAction(encryptWalletAction); settings->addAction(changePassphraseAction); settings->addSeparator(); settings->addAction(optionsAction); QMenu *help = appMenuBar->addMenu(tr("&Help")); help->addAction(openRPCConsoleAction); help->addSeparator(); help->addAction(aboutAction); help->addAction(aboutQtAction); } void BitcoinGUI::createToolBars() { QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolbar->addAction(overviewAction); toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); toolbar->addAction(addressBookAction); } void BitcoinGUI::setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; if(clientModel) { // Create system tray icon and notification createTrayIcon(); // Replace some strings and icons, when using the testnet if(clientModel->isTestNet()) { setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]")); #ifndef Q_OS_MAC QApplication::setWindowIcon(QIcon(":icons/gostcoin_testnet")); setWindowIcon(QIcon(":icons/gostcoin_testnet")); #else MacDockIconHandler::instance()->setIcon(QIcon(":icons/gostcoin_testnet")); #endif if(trayIcon) { // Just attach " [testnet]" to the existing tooltip trayIcon->setToolTip(trayIcon->toolTip() + QString(" ") + tr("[testnet]")); trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); } toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet")); aboutAction->setIcon(QIcon(":/icons/toolbar_testnet")); } // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions, // while the client has not yet fully loaded createTrayIconMenu(); // Keep up to date with client if (clientModel->isI2POnly()) { labelI2POnly->setText("I2P"); labelI2POnly->setToolTip(tr("Wallet is using I2P-network only")); setNumI2PConnections(clientModel->getNumI2PConnections()); connect(clientModel, SIGNAL(numI2PConnectionsChanged(int)), this, SLOT(setNumI2PConnections(int))); } else { labelI2POnly->setText("CLR"); labelI2POnly->setToolTip(tr("Wallet is using mixed or non-I2P (clear) network")); setNumConnections(clientModel->getNumConnections()); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); } if (clientModel->isI2PAddressGenerated()) { labelI2PGenerated->setText("DYN"); labelI2PGenerated->setToolTip(tr("Wallet is running with a random generated I2P-address")); } else { labelI2PGenerated->setText("STA"); labelI2PGenerated->setToolTip(tr("Wallet is running with a static I2P-address")); } setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers()); connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); // Receive and report messages from network/worker thread connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); rpcConsole->setClientModel(clientModel); walletFrame->setClientModel(clientModel); } } bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel) { setWalletActionsEnabled(true); return walletFrame->addWallet(name, walletModel); } bool BitcoinGUI::setCurrentWallet(const QString& name) { return walletFrame->setCurrentWallet(name); } void BitcoinGUI::removeAllWallets() { setWalletActionsEnabled(false); walletFrame->removeAllWallets(); } void BitcoinGUI::setWalletActionsEnabled(bool enabled) { overviewAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); historyAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled); changePassphraseAction->setEnabled(enabled); signMessageAction->setEnabled(enabled); verifyMessageAction->setEnabled(enabled); addressBookAction->setEnabled(enabled); } void BitcoinGUI::createTrayIcon() { #ifndef Q_OS_MAC trayIcon = new QSystemTrayIcon(this); trayIcon->setToolTip(tr("Gostcoin client")); trayIcon->setIcon(QIcon(":/icons/toolbar")); trayIcon->show(); #endif notificator = new Notificator(clientModel->getOptionsModel(), QApplication::applicationName(), trayIcon); } void BitcoinGUI::createTrayIconMenu() { QMenu *trayIconMenu; #ifndef Q_OS_MAC // return if trayIcon is unset (only on non-Mac OSes) if (!trayIcon) return; trayIconMenu = new QMenu(this); trayIcon->setContextMenu(trayIconMenu); connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); #else // Note: On Mac, the dock icon is used to provide the tray's functionality. MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); dockIconHandler->setMainWindow((QMainWindow *)this); trayIconMenu = dockIconHandler->dockMenu(); #endif // Configuration of the tray icon (or dock icon) icon menu trayIconMenu->addAction(toggleHideAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(sendCoinsAction); trayIconMenu->addAction(receiveCoinsAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(optionsAction); trayIconMenu->addAction(openRPCConsoleAction); #ifndef Q_OS_MAC // This is built-in on Mac trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); #endif } #ifndef Q_OS_MAC void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { if(reason == QSystemTrayIcon::Trigger) { // Click on system tray icon triggers show/hide of the main window toggleHideAction->trigger(); } } #endif void BitcoinGUI::saveWindowGeometry() { QSettings settings; settings.setValue("nWindowPos", pos()); settings.setValue("nWindowSize", size()); } void BitcoinGUI::restoreWindowGeometry() { QSettings settings; QPoint pos = settings.value("nWindowPos").toPoint(); QSize size = settings.value("nWindowSize", QSize(850, 550)).toSize(); if (!pos.x() && !pos.y()) { QRect screen = QApplication::desktop()->screenGeometry(); pos.setX((screen.width()-size.width())/2); pos.setY((screen.height()-size.height())/2); } resize(size); move(pos); } void BitcoinGUI::optionsClicked() { if(!clientModel || !clientModel->getOptionsModel()) return; OptionsDialog dlg; dlg.setModel(clientModel->getOptionsModel()); dlg.exec(); } void BitcoinGUI::aboutClicked() { AboutDialog dlg; dlg.setModel(clientModel); dlg.exec(); } void BitcoinGUI::gotoOverviewPage() { if (walletFrame) walletFrame->gotoOverviewPage(); } void BitcoinGUI::gotoHistoryPage() { if (walletFrame) walletFrame->gotoHistoryPage(); } void BitcoinGUI::gotoAddressBookPage() { if (walletFrame) walletFrame->gotoAddressBookPage(); } void BitcoinGUI::gotoReceiveCoinsPage() { if (walletFrame) walletFrame->gotoReceiveCoinsPage(); } void BitcoinGUI::gotoSendCoinsPage(QString addr) { if (walletFrame) walletFrame->gotoSendCoinsPage(addr); } void BitcoinGUI::gotoSignMessageTab(QString addr) { if (walletFrame) walletFrame->gotoSignMessageTab(addr); } void BitcoinGUI::gotoVerifyMessageTab(QString addr) { if (walletFrame) walletFrame->gotoVerifyMessageTab(addr); } void BitcoinGUI::setNumConnections(int count) { QString icon; switch(count) { case 0: icon = ":/icons/connect_0"; break; case 1: case 2: case 3: icon = ":/icons/connect_1"; break; case 4: case 5: case 6: icon = ":/icons/connect_2"; break; case 7: case 8: case 9: icon = ":/icons/connect_3"; break; default: icon = ":/icons/connect_4"; break; } labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Gostcoin network", "", count)); } void BitcoinGUI::setNumI2PConnections(int count) { QString i2pIcon; switch(count) { case 0: i2pIcon = ":/icons/connect_0"; break; case 1: case 2: i2pIcon = ":/icons/connect_1"; break; case 3: case 4: i2pIcon = ":/icons/connect_2"; break; case 5: case 6: i2pIcon = ":/icons/connect_3"; break; default: i2pIcon = ":/icons/connect_4"; break; } labelI2PConnections->setPixmap(QPixmap(i2pIcon)); labelI2PConnections->setToolTip(tr("%n active connection(s) to I2P-Gostcoin network", "", count)); } void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) { // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text) statusBar()->clearMessage(); // Acquire current block source enum BlockSource blockSource = clientModel->getBlockSource(); switch (blockSource) { case BLOCK_SOURCE_NETWORK: progressBarLabel->setText(tr("Synchronizing with network...")); break; case BLOCK_SOURCE_DISK: progressBarLabel->setText(tr("Importing blocks from disk...")); break; case BLOCK_SOURCE_REINDEX: progressBarLabel->setText(tr("Reindexing blocks on disk...")); break; case BLOCK_SOURCE_NONE: // Case: not Importing, not Reindexing and no network connection progressBarLabel->setText(tr("No block source available...")); break; } QString tooltip; QDateTime lastBlockDate = clientModel->getLastBlockDate(); QDateTime currentDate = QDateTime::currentDateTime(); int secs = lastBlockDate.secsTo(currentDate); if(count < nTotalBlocks) { tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks); } else { tooltip = tr("Processed %1 blocks of transaction history.").arg(count); } // Set icon state: spinning if catching up, tick otherwise if(secs < 90*60 && count >= nTotalBlocks) { tooltip = tr("Up to date") + QString(".
") + tooltip; labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); walletFrame->showOutOfSyncWarning(false); progressBarLabel->setVisible(false); progressBar->setVisible(false); } else { // Represent time from last generated block in human readable text QString timeBehindText; if(secs < 48*60*60) { timeBehindText = tr("%n hour(s)","",secs/(60*60)); } else if(secs < 14*24*60*60) { timeBehindText = tr("%n day(s)","",secs/(24*60*60)); } else { timeBehindText = tr("%n week(s)","",secs/(7*24*60*60)); } progressBarLabel->setVisible(true); progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); progressBar->setMaximum(1000000000); progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5); progressBar->setVisible(true); tooltip = tr("Catching up...") + QString("
") + tooltip; labelBlocksIcon->setMovie(syncIconMovie); if(count != prevBlocks) syncIconMovie->jumpToNextFrame(); prevBlocks = count; walletFrame->showOutOfSyncWarning(true); tooltip += QString("
"); tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText); tooltip += QString("
"); tooltip += tr("Transactions after this will not yet be visible."); } // Don't word-wrap this (fixed-width) tooltip tooltip = QString("") + tooltip + QString(""); labelBlocksIcon->setToolTip(tooltip); progressBarLabel->setToolTip(tooltip); progressBar->setToolTip(tooltip); } void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret) { QString strTitle = tr("Gostcoin"); // default title // Default to information icon int nMBoxIcon = QMessageBox::Information; int nNotifyIcon = Notificator::Information; // Override title based on style QString msgType; switch (style) { case CClientUIInterface::MSG_ERROR: msgType = tr("Error"); break; case CClientUIInterface::MSG_WARNING: msgType = tr("Warning"); break; case CClientUIInterface::MSG_INFORMATION: msgType = tr("Information"); break; default: msgType = title; // Use supplied title } if (!msgType.isEmpty()) strTitle += " - " + msgType; // Check for error/warning icon if (style & CClientUIInterface::ICON_ERROR) { nMBoxIcon = QMessageBox::Critical; nNotifyIcon = Notificator::Critical; } else if (style & CClientUIInterface::ICON_WARNING) { nMBoxIcon = QMessageBox::Warning; nNotifyIcon = Notificator::Warning; } // Display message if (style & CClientUIInterface::MODAL) { // Check for buttons, use OK as default, if none was supplied QMessageBox::StandardButton buttons; if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK))) buttons = QMessageBox::Ok; QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons); int r = mBox.exec(); if (ret != NULL) *ret = r == QMessageBox::Ok; } else notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message); } void BitcoinGUI::changeEvent(QEvent *e) { QMainWindow::changeEvent(e); #ifndef Q_OS_MAC // Ignored on Mac if(e->type() == QEvent::WindowStateChange) { if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) { QWindowStateChangeEvent *wsevt = static_cast(e); if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) { QTimer::singleShot(0, this, SLOT(hide())); e->ignore(); } } } #endif } void BitcoinGUI::closeEvent(QCloseEvent *event) { if(clientModel) { #ifndef Q_OS_MAC // Ignored on Mac if(!clientModel->getOptionsModel()->getMinimizeToTray() && !clientModel->getOptionsModel()->getMinimizeOnClose()) { QApplication::quit(); } #endif } QMainWindow::closeEvent(event); } void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) { QString strMessage = tr("This transaction is over the size limit. You can still send it for a fee of %1, " "which goes to the nodes that process your transaction and helps to support the network. " "Do you want to pay the fee?").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired)); QMessageBox::StandardButton retval = QMessageBox::question( this, tr("Confirm transaction fee"), strMessage, QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); *payFee = (retval == QMessageBox::Yes); } void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address) { // On new transaction, make an info balloon message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"), tr("Date: %1\n" "Amount: %2\n" "Type: %3\n" "Address: %4\n") .arg(date) .arg(BitcoinUnits::formatWithUnit(unit, amount, true)) .arg(type) .arg(address), CClientUIInterface::MSG_INFORMATION); } void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) { // Accept only URIs if(event->mimeData()->hasUrls()) event->acceptProposedAction(); } void BitcoinGUI::dropEvent(QDropEvent *event) { if(event->mimeData()->hasUrls()) { int nValidUrisFound = 0; QList uris = event->mimeData()->urls(); foreach(const QUrl &uri, uris) { if (walletFrame->handleURI(uri.toString())) nValidUrisFound++; } // if valid URIs were found if (nValidUrisFound) walletFrame->gotoSendCoinsPage(); else message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Gostcoin address or malformed URI parameters."), CClientUIInterface::ICON_WARNING); } event->acceptProposedAction(); } bool BitcoinGUI::eventFilter(QObject *object, QEvent *event) { // Catch status tip events if (event->type() == QEvent::StatusTip) { // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff if (progressBarLabel->isVisible() || progressBar->isVisible()) return true; } return QMainWindow::eventFilter(object, event); } void BitcoinGUI::handleURI(QString strURI) { // URI has to be valid if (!walletFrame->handleURI(strURI)) message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Gostcoin address or malformed URI parameters."), CClientUIInterface::ICON_WARNING); } void BitcoinGUI::showGeneratedI2PAddr(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName) { ShowI2PAddresses i2pDialog(caption, pub, priv, b32, configFileName, this); i2pDialog.exec(); } void BitcoinGUI::setEncryptionStatus(int status) { switch(status) { case WalletModel::Unencrypted: labelEncryptionIcon->hide(); encryptWalletAction->setChecked(false); changePassphraseAction->setEnabled(false); encryptWalletAction->setEnabled(true); break; case WalletModel::Unlocked: labelEncryptionIcon->show(); labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported break; case WalletModel::Locked: labelEncryptionIcon->show(); labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported break; } } void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden) { // activateWindow() (sometimes) helps with keyboard focus on Windows if (isHidden()) { show(); activateWindow(); } else if (isMinimized()) { showNormal(); activateWindow(); } else if (GUIUtil::isObscured(this)) { raise(); activateWindow(); } else if(fToggleHidden) hide(); } void BitcoinGUI::toggleHidden() { showNormalIfMinimized(true); } void BitcoinGUI::detectShutdown() { if (ShutdownRequested()) QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); }