X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fbitcoingui.cpp;h=81cebfb4a45d530c7ed7e7c2b6f11e709a98f54e;hb=01ea41b203d86d8577227a17760a54578630a3d2;hp=0c66bd4ca7489967781e5b5f3cd06dbd6ccca811;hpb=4a843976e094eee9eb8528f7828f389bd31c462e;p=novacoin.git diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 0c66bd4..81cebfb 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -11,13 +11,20 @@ #include "aboutdialog.h" #include "clientmodel.h" #include "walletmodel.h" -#include "guiutil.h" #include "editaddressdialog.h" #include "optionsmodel.h" #include "transactiondescdialog.h" #include "addresstablemodel.h" #include "transactionview.h" #include "overviewpage.h" +#include "bitcoinunits.h" +#include "guiconstants.h" +#include "askpassphrasedialog.h" +#include "notificator.h" + +#ifdef Q_WS_MAC +#include "macdockiconhandler.h" +#endif #include #include @@ -36,8 +43,10 @@ #include #include #include +#include -#include +#include +#include #include @@ -45,49 +54,42 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): QMainWindow(parent), clientModel(0), walletModel(0), - trayIcon(0) + encryptWalletAction(0), + changePassphraseAction(0), + aboutQtAction(0), + trayIcon(0), + notificator(0) { resize(850, 550); setWindowTitle(tr("Bitcoin Wallet")); +#ifndef Q_WS_MAC setWindowIcon(QIcon(":icons/bitcoin")); - +#else + setUnifiedTitleAndToolBarOnMac(true); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); +#endif + // Accept D&D of URIs + setAcceptDrops(true); + + // Create actions for the toolbar, menu bar and tray/dock icon createActions(); - // Menus - QMenu *file = menuBar()->addMenu("&File"); - file->addAction(sendCoinsAction); - file->addAction(receiveCoinsAction); - file->addSeparator(); - file->addAction(quitAction); - - QMenu *settings = menuBar()->addMenu("&Settings"); - settings->addAction(optionsAction); + // Create application menu bar + createMenuBar(); - QMenu *help = menuBar()->addMenu("&Help"); - help->addAction(aboutAction); - - // Toolbar - QToolBar *toolbar = addToolBar("Main toolbar"); - toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - toolbar->addAction(overviewAction); - toolbar->addAction(sendCoinsAction); - toolbar->addAction(receiveCoinsAction); - toolbar->addAction(historyAction); - toolbar->addAction(addressBookAction); + // Create the toolbars + createToolBars(); - QToolBar *toolbar2 = addToolBar("Transactions toolbar"); - toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - toolbar2->addAction(exportAction); + // Create the tray icon (or setup the dock icon) + createTrayIcon(); - // Overview page + // Create tabs overviewPage = new OverviewPage(); - QVBoxLayout *vbox = new QVBoxLayout(); + transactionsPage = new QWidget(this); + QVBoxLayout *vbox = new QVBoxLayout(); transactionView = new TransactionView(this); - connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), transactionView, SLOT(transactionDetails())); vbox->addWidget(transactionView); - - transactionsPage = new QWidget(this); transactionsPage->setLayout(vbox); addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab); @@ -103,21 +105,29 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); setCentralWidget(centralWidget); - + // Create status bar statusBar(); - labelConnections = new QLabel(); - labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelConnections->setMinimumWidth(150); - labelConnections->setMaximumWidth(150); - labelConnections->setToolTip(tr("Number of connections to other clients")); - - labelBlocks = new QLabel(); - labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelBlocks->setMinimumWidth(150); - labelBlocks->setMaximumWidth(150); - labelBlocks->setToolTip(tr("Number of blocks in the block chain")); + // Status bar notification icons + QFrame *frameBlocks = new QFrame(); + //frameBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken); + 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 for blocks download progressBarLabel = new QLabel(tr("Synchronizing with network...")); @@ -128,140 +138,254 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): statusBar()->addWidget(progressBarLabel); statusBar()->addWidget(progressBar); - statusBar()->addPermanentWidget(labelConnections); - statusBar()->addPermanentWidget(labelBlocks); + statusBar()->addPermanentWidget(frameBlocks); - createTrayIcon(); + syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this); + + // Clicking on a transaction on the overview page simply sends you to transaction history page + connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage())); + + // Doubleclicking on a transaction on the transaction history page shows details + connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); gotoOverviewPage(); } +BitcoinGUI::~BitcoinGUI() +{ +#ifdef Q_WS_MAC + delete appMenuBar; +#endif +} + void BitcoinGUI::createActions() { QActionGroup *tabGroup = new QActionGroup(this); overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this); + overviewAction->setToolTip(tr("Show general overview of wallet")); overviewAction->setCheckable(true); + overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); tabGroup->addAction(overviewAction); historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); + historyAction->setToolTip(tr("Browse transaction history")); historyAction->setCheckable(true); + historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(historyAction); addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this); addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels")); addressBookAction->setCheckable(true); + addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); tabGroup->addAction(addressBookAction); receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this); receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments")); receiveCoinsAction->setCheckable(true); + receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); tabGroup->addAction(receiveCoinsAction); sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this); sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address")); sendCoinsAction->setCheckable(true); + sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); + connect(overviewAction, SIGNAL(triggered()), this, SLOT(show())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); + connect(historyAction, SIGNAL(triggered()), this, SLOT(show())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); + connect(addressBookAction, SIGNAL(triggered()), this, SLOT(show())); connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); + connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(show())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); + connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(show())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); - quitAction = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this); + quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setToolTip(tr("Quit application")); - aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this); + quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + quitAction->setMenuRole(QAction::QuitRole); + aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About %1").arg(qApp->applicationName()), this); aboutAction->setToolTip(tr("Show information about Bitcoin")); + aboutAction->setMenuRole(QAction::AboutRole); + aboutQtAction = new QAction(tr("About &Qt"), this); + aboutQtAction->setToolTip(tr("Show information about Qt")); + aboutQtAction->setMenuRole(QAction::AboutQtRole); optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); optionsAction->setToolTip(tr("Modify configuration options for bitcoin")); + optionsAction->setMenuRole(QAction::PreferencesRole); openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this); openBitcoinAction->setToolTip(tr("Show the Bitcoin window")); exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this); - exportAction->setToolTip(tr("Export data in current view to a file")); + exportAction->setToolTip(tr("Export the current view to a file")); + encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this); + encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet")); + encryptWalletAction->setCheckable(true); + changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase"), this); + changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked())); - connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(show())); + connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormal())); + connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); + connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); +} + +void BitcoinGUI::createMenuBar() +{ +#ifdef Q_WS_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(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(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); + + QToolBar *toolbar2 = addToolBar(tr("Actions toolbar")); + toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + toolbar2->addAction(exportAction); } void BitcoinGUI::setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; - - if(clientModel->isTestNet()) + if(clientModel) { - QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]"); - setWindowTitle(title_testnet); - setWindowIcon(QIcon(":icons/bitcoin_testnet")); - if(trayIcon) + if(clientModel->isTestNet()) { - trayIcon->setToolTip(title_testnet); - trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); + QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]"); + setWindowTitle(title_testnet); +#ifndef Q_WS_MAC + setWindowIcon(QIcon(":icons/bitcoin_testnet")); +#else + MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet")); +#endif + if(trayIcon) + { + trayIcon->setToolTip(title_testnet); + trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); + } } - } - // Keep up to date with client - setNumConnections(clientModel->getNumConnections()); - connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + // Keep up to date with client + setNumConnections(clientModel->getNumConnections()); + connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks()); - connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); + setNumBlocks(clientModel->getNumBlocks()); + connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); - // Report errors from network/worker thread - connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); + // Report errors from network/worker thread + connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); + } } void BitcoinGUI::setWalletModel(WalletModel *walletModel) { this->walletModel = walletModel; + if(walletModel) + { + // Report errors from wallet thread + connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); - // Report errors from wallet thread - connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); + // Put transaction list in tabs + transactionView->setModel(walletModel); - // Put transaction list in tabs - transactionView->setModel(walletModel); + overviewPage->setModel(walletModel); + addressBookPage->setModel(walletModel->getAddressTableModel()); + receiveCoinsPage->setModel(walletModel->getAddressTableModel()); + sendCoinsPage->setModel(walletModel); - overviewPage->setModel(walletModel); - addressBookPage->setModel(walletModel->getAddressTableModel()); - receiveCoinsPage->setModel(walletModel->getAddressTableModel()); - sendCoinsPage->setModel(walletModel); + setEncryptionStatus(walletModel->getEncryptionStatus()); + connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); - // Balloon popup for new transaction - connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(incomingTransaction(const QModelIndex &, int, int))); + // Balloon popup for new transaction + connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(incomingTransaction(QModelIndex,int,int))); + + // Ask for passphrase if needed + connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); + } } void BitcoinGUI::createTrayIcon() { - QMenu *trayIconMenu = new QMenu(this); - trayIconMenu->addAction(openBitcoinAction); - trayIconMenu->addAction(sendCoinsAction); - trayIconMenu->addAction(optionsAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(quitAction); - + QMenu *trayIconMenu; +#ifndef Q_WS_MAC trayIcon = new QSystemTrayIcon(this); + trayIconMenu = new QMenu(this); trayIcon->setContextMenu(trayIconMenu); trayIcon->setToolTip("Bitcoin client"); trayIcon->setIcon(QIcon(":/icons/toolbar")); connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); trayIcon->show(); +#else + // Note: On Mac, the dock icon is used to provide the tray's functionality. + MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); + connect(dockIconHandler, SIGNAL(dockIconClicked()), openBitcoinAction, SLOT(trigger())); + trayIconMenu = dockIconHandler->dockMenu(); +#endif + + // Configuration of the tray icon (or dock icon) icon menu + trayIconMenu->addAction(openBitcoinAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(receiveCoinsAction); + trayIconMenu->addAction(sendCoinsAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(optionsAction); +#ifndef Q_WS_MAC // This is built-in on Mac + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); +#endif + + notificator = new Notificator(tr("bitcoin-qt"), trayIcon); } +#ifndef Q_WS_MAC void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { - if(reason == QSystemTrayIcon::DoubleClick) + if(reason == QSystemTrayIcon::Trigger) { - // Doubleclick on system tray icon triggers "open bitcoin" + // Click on system tray icon triggers "open bitcoin" openBitcoinAction->trigger(); } + } +#endif void BitcoinGUI::optionsClicked() { + if(!clientModel || !clientModel->getOptionsModel()) + return; OptionsDialog dlg; dlg.setModel(clientModel->getOptionsModel()); dlg.exec(); @@ -285,37 +409,42 @@ void BitcoinGUI::setNumConnections(int count) case 7: case 8: case 9: icon = ":/icons/connect_3"; break; default: icon = ":/icons/connect_4"; break; } - labelConnections->setTextFormat(Qt::RichText); - labelConnections->setText(" " + tr("%n connection(s)", "", count)); + 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 total = clientModel->getTotalBlocksEstimate(); + if(!clientModel) + return; + int initTotal = clientModel->getNumBlocksAtStartup(); + int total = clientModel->getNumBlocksOfPeers(); + QString tooltip; + if(count < total) { progressBarLabel->setVisible(true); progressBar->setVisible(true); - progressBar->setMaximum(total); - progressBar->setValue(count); + progressBar->setMaximum(total - initTotal); + progressBar->setValue(count - initTotal); + tooltip = tr("Downloaded %1 of %2 blocks of transaction history.").arg(count).arg(total); } else { progressBarLabel->setVisible(false); progressBar->setVisible(false); + tooltip = tr("Downloaded %1 blocks of transaction history.").arg(count); } QDateTime now = QDateTime::currentDateTime(); QDateTime lastBlockDate = clientModel->getLastBlockDate(); int secs = lastBlockDate.secsTo(now); QString text; - QString icon = ":/icons/notsynced"; - // "Up to date" icon, and outdated icon - if(secs < 30*60) + // Represent time from last generated block in human readable text + if(secs < 60) { - text = "Up to date"; - icon = ":/icons/synced"; + text = tr("%n second(s) ago","",secs); } else if(secs < 60*60) { @@ -330,54 +459,67 @@ void BitcoinGUI::setNumBlocks(int count) text = tr("%n day(s) ago","",secs/(60*60*24)); } - labelBlocks->setText(" " + text); - labelBlocks->setToolTip(tr("Downloaded %n block(s) of transaction history. Last block was generated %1.", "", count) - .arg(QLocale::system().toString(lastBlockDate))); -} - -void BitcoinGUI::error(const QString &title, const QString &message) -{ - // Report errors from network/worker thread - if(trayIcon->supportsMessages()) + // Set icon state: spinning if catching up, tick otherwise + if(secs < 30*60) { - // Show as "balloon" message if possible - trayIcon->showMessage(title, message, QSystemTrayIcon::Critical); + tooltip = tr("Up to date") + QString("\n") + tooltip; + labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); } else { - // Fall back to old fashioned popup dialog if not - QMessageBox::critical(this, title, - message, - QMessageBox::Ok, QMessageBox::Ok); + tooltip = tr("Catching up...") + QString("\n") + tooltip; + labelBlocksIcon->setMovie(syncIconMovie); + syncIconMovie->start(); } + + tooltip += QString("\n"); + tooltip += tr("Last received block was generated %1.").arg(text); + + labelBlocksIcon->setToolTip(tooltip); + progressBarLabel->setToolTip(tooltip); + progressBar->setToolTip(tooltip); +} + +void BitcoinGUI::error(const QString &title, const QString &message) +{ + // Report errors from network/worker thread + notificator->notify(Notificator::Critical, title, message); } void BitcoinGUI::changeEvent(QEvent *e) { - if (e->type() == QEvent::WindowStateChange) +#ifndef Q_WS_MAC // Ignored on Mac + if(e->type() == QEvent::WindowStateChange) { - if(clientModel->getOptionsModel()->getMinimizeToTray()) + if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) { - if (isMinimized()) + if(isMinimized()) { hide(); e->ignore(); } else { + show(); e->accept(); } } } +#endif QMainWindow::changeEvent(e); } void BitcoinGUI::closeEvent(QCloseEvent *event) { - if(!clientModel->getOptionsModel()->getMinimizeToTray() && - !clientModel->getOptionsModel()->getMinimizeOnClose()) + if(clientModel) { - qApp->quit(); +#ifndef Q_WS_MAC // Ignored on Mac + if(!clientModel->getOptionsModel()->getMinimizeToTray() && + !clientModel->getOptionsModel()->getMinimizeOnClose()) + { + qApp->quit(); + } +#endif } QMainWindow::closeEvent(event); } @@ -387,7 +529,8 @@ 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(GUIUtil::formatMoney(nFeeRequired)); + "Do you want to pay the fee?").arg( + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired)); QMessageBox::StandardButton retval = QMessageBox::question( this, tr("Sending..."), strMessage, QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); @@ -396,12 +539,14 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end) { + if(!walletModel || !clientModel) + return; TransactionTableModel *ttm = walletModel->getTransactionTableModel(); qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent) .data(Qt::EditRole).toULongLong(); if(!clientModel->inInitialBlockDownload()) { - // On incoming transaction, make an info balloon + // On new transaction, make an info balloon // Unless the initial block download is in progress, to prevent balloon-spam QString date = ttm->index(start, TransactionTableModel::Date, parent) .data().toString(); @@ -409,14 +554,21 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int .data().toString(); QString address = ttm->index(start, TransactionTableModel::ToAddress, parent) .data().toString(); - - trayIcon->showMessage((amount)<0 ? tr("Sent transaction") : - tr("Incoming transaction"), - tr("Date: ") + date + "\n" + - tr("Amount: ") + GUIUtil::formatMoney(amount, true) + "\n" + - tr("Type: ") + type + "\n" + - tr("Address: ") + address + "\n", - QSystemTrayIcon::Information); + QIcon icon = qvariant_cast(ttm->index(start, + TransactionTableModel::ToAddress, parent) + .data(Qt::DecorationRole)); + + notificator->notify(Notificator::Information, + (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(walletModel->getOptionsModel()->getDisplayUnit(), amount, true)) + .arg(type) + .arg(address), icon); } } @@ -462,10 +614,91 @@ void BitcoinGUI::gotoReceiveCoinsPage() void BitcoinGUI::gotoSendCoinsPage() { sendCoinsAction->setChecked(true); - sendCoinsPage->clear(); centralWidget->setCurrentWidget(sendCoinsPage); exportAction->setEnabled(false); disconnect(exportAction, SIGNAL(triggered()), 0, 0); } +void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) +{ + // Accept only URLs + if(event->mimeData()->hasUrls()) + event->acceptProposedAction(); +} + +void BitcoinGUI::dropEvent(QDropEvent *event) +{ + if(event->mimeData()->hasUrls()) + { + gotoSendCoinsPage(); + QList urls = event->mimeData()->urls(); + foreach(const QUrl &url, urls) + { + sendCoinsPage->handleURL(&url); + } + } + + event->acceptProposedAction(); +} + +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::encryptWallet(bool status) +{ + if(!walletModel) + return; + AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt: + AskPassphraseDialog::Decrypt, this); + dlg.setModel(walletModel); + dlg.exec(); + + setEncryptionStatus(walletModel->getEncryptionStatus()); +} + +void BitcoinGUI::changePassphrase() +{ + AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this); + dlg.setModel(walletModel); + dlg.exec(); +} + +void BitcoinGUI::unlockWallet() +{ + if(!walletModel) + return; + // Unlock wallet when requested by wallet model + if(walletModel->getEncryptionStatus() == WalletModel::Locked) + { + AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this); + dlg.setModel(walletModel); + dlg.exec(); + } +}