dogecoin/src/qt/bitcoingui.cpp
Wladimir J. van der Laan 45155d3010 qt: move export button to tabs
Having the export button at the top was confusing people into thinking
the entire wallet was exported.

This commit moves the export button to the address book, receiving
addresses and transaction tabs separately.
2013-04-12 13:13:32 +02:00

822 lines
28 KiB
C++

/*
* Qt4 bitcoin GUI.
*
* W.J. van der Laan 2011-2012
* The Bitcoin Developers 2011-2012
*/
#include <QApplication>
#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"
#ifdef Q_OS_MAC
#include "macdockiconhandler.h"
#endif
#include <QMenuBar>
#include <QMenu>
#include <QIcon>
#include <QVBoxLayout>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QMessageBox>
#include <QProgressBar>
#include <QStackedWidget>
#include <QDateTime>
#include <QMovie>
#include <QFileDialog>
#include <QDesktopServices>
#include <QTimer>
#include <QDragEnterEvent>
#include <QUrl>
#include <QMimeData>
#include <QStyle>
#include <QSettings>
#include <QDesktopWidget>
#include <QListWidget>
#include <iostream>
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("Bitcoin") + " - " + tr("Wallet"));
#ifndef Q_OS_MAC
QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
setWindowIcon(QIcon(":icons/bitcoin"));
#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 system tray icon and notification
createTrayIcon();
// 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();
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelEncryptionIcon);
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelConnectionsIcon);
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelBlocksIcon);
frameBlocksLayout->addStretch();
// 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);
}
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;
#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 Bitcoin 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/bitcoin"), tr("&About Bitcoin"), this);
aboutAction->setStatusTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutRole);
aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), 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 Bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole);
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), 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 Bitcoin 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 Bitcoin 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()));
}
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();
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)
{
// 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/bitcoin_testnet"));
setWindowIcon(QIcon(":icons/bitcoin_testnet"));
#else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_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
setNumConnections(clientModel->getNumConnections());
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
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)
{
return walletFrame->addWallet(name, walletModel);
}
bool BitcoinGUI::setCurrentWallet(const QString& name)
{
return walletFrame->setCurrentWallet(name);
}
void BitcoinGUI::removeAllWallets()
{
walletFrame->removeAllWallets();
}
void BitcoinGUI::createTrayIcon()
{
#ifndef Q_OS_MAC
trayIcon = new QSystemTrayIcon(this);
trayIcon->setToolTip(tr("Bitcoin client"));
trayIcon->setIcon(QIcon(":/icons/toolbar"));
trayIcon->show();
#endif
notificator = new Notificator(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();
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 Bitcoin 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();
// don't show / hide progress bar and its label if we have no connection to the network
enum BlockSource blockSource = clientModel ? clientModel->getBlockSource() : BLOCK_SOURCE_NONE;
if (blockSource == BLOCK_SOURCE_NONE || (blockSource == BLOCK_SOURCE_NETWORK && clientModel->getNumConnections() == 0))
{
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
return;
}
QString tooltip;
QString importText;
switch (blockSource) {
case BLOCK_SOURCE_NONE:
case BLOCK_SOURCE_NETWORK:
importText = tr("Synchronizing with network...");
break;
case BLOCK_SOURCE_DISK:
importText = tr("Importing blocks from disk...");
break;
case BLOCK_SOURCE_REINDEX:
importText = tr("Reindexing blocks on disk...");
}
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(".<br>") + 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->setText(importText);
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("<br>") + tooltip;
labelBlocksIcon->setMovie(syncIconMovie);
if(count != prevBlocks)
syncIconMovie->jumpToNextFrame();
prevBlocks = count;
walletFrame->showOutOfSyncWarning(true);
tooltip += QString("<br>");
tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
tooltip += QString("<br>");
tooltip += tr("Transactions after this will not yet be visible.");
}
// Don't word-wrap this (fixed-width) tooltip
tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
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("Bitcoin") + " - ";
// Default to information icon
int nMBoxIcon = QMessageBox::Information;
int nNotifyIcon = Notificator::Information;
// Check for usage of predefined title
switch (style) {
case CClientUIInterface::MSG_ERROR:
strTitle += tr("Error");
break;
case CClientUIInterface::MSG_WARNING:
strTitle += tr("Warning");
break;
case CClientUIInterface::MSG_INFORMATION:
strTitle += tr("Information");
break;
default:
strTitle += title; // Use supplied title
}
// 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<QWindowStateChangeEvent*>(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<QUrl> 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 Bitcoin 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 Bitcoin address or malformed URI parameters."),
CClientUIInterface::ICON_WARNING);
}
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 <b>encrypted</b> and currently <b>unlocked</b>"));
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 <b>encrypted</b> and currently <b>locked</b>"));
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);
}