X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fbitcoingui.cpp;h=ed687c4532e55740491674e4de2bb90dd0fde982;hb=8dcffd4d0717e71226da8c3a848b7b6905074637;hp=fbab51bd6bb366d97d1546831e99a7cbaed9584c;hpb=d52a0f3bca2c8df8360308b062185d803e34f0d9;p=novacoin.git diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index fbab51b..ed687c4 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -5,7 +5,7 @@ */ #include "bitcoingui.h" #include "transactiontablemodel.h" -#include "addressbookdialog.h" +#include "addressbookpage.h" #include "sendcoinsdialog.h" #include "optionsdialog.h" #include "aboutdialog.h" @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include @@ -54,55 +56,87 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): // Menus QMenu *file = menuBar()->addMenu("&File"); - file->addAction(sendCoins); - file->addAction(receiveCoins); + file->addAction(sendCoinsAction); + file->addAction(receiveCoinsAction); file->addSeparator(); - file->addAction(quit); + file->addAction(quitAction); QMenu *settings = menuBar()->addMenu("&Settings"); - settings->addAction(options); + settings->addAction(optionsAction); QMenu *help = menuBar()->addMenu("&Help"); - help->addAction(about); + 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->addSeparator(); - toolbar->addAction(sendCoins); - toolbar->addAction(receiveCoins); - toolbar->addAction(addressbook); + toolbar->addAction(addressBookAction); - overviewPage = new OverviewPage(); + QToolBar *toolbar2 = addToolBar("Transactions toolbar"); + toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + toolbar2->addAction(exportAction); + // Overview page + overviewPage = new OverviewPage(); QVBoxLayout *vbox = new QVBoxLayout(); transactionView = new TransactionView(this); - connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(transactionDetails(const QModelIndex&))); + connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), transactionView, SLOT(showDetails())); vbox->addWidget(transactionView); transactionsPage = new QWidget(this); transactionsPage->setLayout(vbox); + addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab); + + receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab); + + sendCoinsPage = new SendCoinsDialog(this); + centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); centralWidget->addWidget(transactionsPage); + centralWidget->addWidget(addressBookPage); + centralWidget->addWidget(receiveCoinsPage); + centralWidget->addWidget(sendCoinsPage); setCentralWidget(centralWidget); // Create status bar statusBar(); + // Status bar "Connections" notification + QFrame *frameConnections = new QFrame(); + frameConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken); + frameConnections->setMinimumWidth(150); + frameConnections->setMaximumWidth(150); + QHBoxLayout *frameConnectionsLayout = new QHBoxLayout(frameConnections); + frameConnectionsLayout->setContentsMargins(3,0,3,0); + frameConnectionsLayout->setSpacing(3); + labelConnectionsIcon = new QLabel(); + labelConnectionsIcon->setToolTip(tr("Number of connections to other clients")); + frameConnectionsLayout->addWidget(labelConnectionsIcon); labelConnections = new QLabel(); - labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelConnections->setMinimumWidth(150); labelConnections->setToolTip(tr("Number of connections to other clients")); - + frameConnectionsLayout->addWidget(labelConnections); + frameConnectionsLayout->addStretch(); + + // Status bar "Blocks" notification + QFrame *frameBlocks = new QFrame(); + frameBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken); + frameBlocks->setMinimumWidth(150); + frameBlocks->setMaximumWidth(150); + QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks); + frameBlocksLayout->setContentsMargins(3,0,3,0); + frameBlocksLayout->setSpacing(3); + labelBlocksIcon = new QLabel(); + frameBlocksLayout->addWidget(labelBlocksIcon); labelBlocks = new QLabel(); - labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelBlocks->setMinimumWidth(130); - labelBlocks->setToolTip(tr("Number of blocks in the block chain")); + frameBlocksLayout->addWidget(labelBlocks); + frameBlocksLayout->addStretch(); // Progress bar for blocks download progressBarLabel = new QLabel(tr("Synchronizing with network...")); @@ -113,49 +147,64 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): statusBar()->addWidget(progressBarLabel); statusBar()->addWidget(progressBar); - statusBar()->addPermanentWidget(labelConnections); - statusBar()->addPermanentWidget(labelBlocks); + statusBar()->addPermanentWidget(frameConnections); + statusBar()->addPermanentWidget(frameBlocks); createTrayIcon(); - gotoOverviewTab(); + syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this); + + gotoOverviewPage(); } void BitcoinGUI::createActions() { QActionGroup *tabGroup = new QActionGroup(this); + overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this); overviewAction->setCheckable(true); tabGroup->addAction(overviewAction); + historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setCheckable(true); tabGroup->addAction(historyAction); - connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewTab())); - connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryTab())); - - quit = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this); - quit->setToolTip(tr("Quit application")); - sendCoins = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this); - sendCoins->setToolTip(tr("Send coins to a bitcoin address")); - addressbook = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this); - addressbook->setToolTip(tr("Edit the list of stored addresses and labels")); - about = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this); - about->setToolTip(tr("Show information about Bitcoin")); - receiveCoins = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this); - receiveCoins->setToolTip(tr("Show the list of addresses for receiving payments")); - options = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); - options->setToolTip(tr("Modify configuration options for bitcoin")); - openBitcoin = new QAction(QIcon(":/icons/bitcoin"), "Open &Bitcoin", this); - openBitcoin->setToolTip(tr("Show the Bitcoin window")); - - connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); - connect(sendCoins, SIGNAL(triggered()), this, SLOT(sendCoinsClicked())); - connect(addressbook, SIGNAL(triggered()), this, SLOT(addressbookClicked())); - connect(receiveCoins, SIGNAL(triggered()), this, SLOT(receiveCoinsClicked())); - connect(options, SIGNAL(triggered()), this, SLOT(optionsClicked())); - connect(about, SIGNAL(triggered()), this, SLOT(aboutClicked())); - connect(openBitcoin, SIGNAL(triggered()), this, SLOT(show())); + 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); + 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); + 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); + tabGroup->addAction(sendCoinsAction); + + connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); + connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); + connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); + connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); + connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); + + quitAction = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this); + quitAction->setToolTip(tr("Quit application")); + aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this); + aboutAction->setToolTip(tr("Show information about Bitcoin")); + optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); + optionsAction->setToolTip(tr("Modify configuration options for bitcoin")); + 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")); + + 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())); } void BitcoinGUI::setClientModel(ClientModel *clientModel) @@ -164,7 +213,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) if(clientModel->isTestNet()) { - QString title_testnet = tr("Bitcoin Wallet [testnet]"); + QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]"); setWindowTitle(title_testnet); setWindowIcon(QIcon(":icons/bitcoin_testnet")); if(trayIcon) @@ -189,18 +238,16 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) { this->walletModel = walletModel; - // Keep up to date with wallet - setBalance(walletModel->getBalance()); - connect(walletModel, SIGNAL(balanceChanged(qint64)), this, SLOT(setBalance(qint64))); - - setNumTransactions(walletModel->getNumTransactions()); - connect(walletModel, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int))); - // Report errors from wallet thread connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); // Put transaction list in tabs - transactionView->setModel(walletModel->getTransactionTableModel()); + transactionView->setModel(walletModel); + + overviewPage->setModel(walletModel); + addressBookPage->setModel(walletModel->getAddressTableModel()); + receiveCoinsPage->setModel(walletModel->getAddressTableModel()); + sendCoinsPage->setModel(walletModel); // Balloon popup for new transaction connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), @@ -210,11 +257,11 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) void BitcoinGUI::createTrayIcon() { QMenu *trayIconMenu = new QMenu(this); - trayIconMenu->addAction(openBitcoin); - trayIconMenu->addAction(sendCoins); - trayIconMenu->addAction(options); + trayIconMenu->addAction(openBitcoinAction); + trayIconMenu->addAction(sendCoinsAction); + trayIconMenu->addAction(optionsAction); trayIconMenu->addSeparator(); - trayIconMenu->addAction(quit); + trayIconMenu->addAction(quitAction); trayIcon = new QSystemTrayIcon(this); trayIcon->setContextMenu(trayIconMenu); @@ -230,33 +277,10 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) if(reason == QSystemTrayIcon::DoubleClick) { // Doubleclick on system tray icon triggers "open bitcoin" - openBitcoin->trigger(); + openBitcoinAction->trigger(); } } -void BitcoinGUI::sendCoinsClicked() -{ - SendCoinsDialog dlg; - dlg.setModel(walletModel); - dlg.exec(); -} - -void BitcoinGUI::addressbookClicked() -{ - AddressBookDialog dlg(AddressBookDialog::ForEditing); - dlg.setModel(walletModel->getAddressTableModel()); - dlg.setTab(AddressBookDialog::SendingTab); - dlg.exec(); -} - -void BitcoinGUI::receiveCoinsClicked() -{ - AddressBookDialog dlg(AddressBookDialog::ForEditing); - dlg.setModel(walletModel->getAddressTableModel()); - dlg.setTab(AddressBookDialog::ReceivingTab); - dlg.exec(); -} - void BitcoinGUI::optionsClicked() { OptionsDialog dlg; @@ -271,11 +295,6 @@ void BitcoinGUI::aboutClicked() dlg.exec(); } -void BitcoinGUI::setBalance(qint64 balance) -{ - overviewPage->setBalance(balance); -} - void BitcoinGUI::setNumConnections(int count) { QString icon; @@ -287,32 +306,72 @@ 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(16,16)); + labelConnections->setText(tr("%n connection(s)", "", count)); } void BitcoinGUI::setNumBlocks(int count) { int total = clientModel->getTotalBlocksEstimate(); + QString tooltip; + if(count < total) { progressBarLabel->setVisible(true); progressBar->setVisible(true); progressBar->setMaximum(total); progressBar->setValue(count); + 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); } - labelBlocks->setText(tr("%n block(s)", "", count)); -} + QDateTime now = QDateTime::currentDateTime(); + QDateTime lastBlockDate = clientModel->getLastBlockDate(); + int secs = lastBlockDate.secsTo(now); + QString text; + bool spinning = true; -void BitcoinGUI::setNumTransactions(int count) -{ - overviewPage->setNumTransactions(count); + // "Up to date" icon, and outdated icon + if(secs < 30*60) + { + text = "Up to date"; + spinning = false; + } + else if(secs < 60*60) + { + text = tr("%n minute(s) ago","",secs/60); + } + else if(secs < 24*60*60) + { + text = tr("%n hour(s) ago","",secs/(60*60)); + } + else + { + text = tr("%n day(s) ago","",secs/(60*60*24)); + } + tooltip += QString("\n"); + tooltip += tr("Last received block was generated %1.").arg(text); + + if(spinning) + { + labelBlocksIcon->setMovie(syncIconMovie); + syncIconMovie->start(); + } + else + { + labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(16,16)); + } + labelBlocks->setText(text); + + labelBlocksIcon->setToolTip(tooltip); + labelBlocks->setToolTip(tooltip); + progressBarLabel->setToolTip(tooltip); + progressBar->setToolTip(tooltip); } void BitcoinGUI::error(const QString &title, const QString &message) @@ -374,19 +433,12 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) *payFee = (retval == QMessageBox::Yes); } -void BitcoinGUI::transactionDetails(const QModelIndex& idx) -{ - // A transaction is doubleclicked - TransactionDescDialog dlg(idx); - dlg.exec(); -} - void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end) { TransactionTableModel *ttm = walletModel->getTransactionTableModel(); qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent) .data(Qt::EditRole).toULongLong(); - if(amount>0 && !clientModel->inInitialBlockDownload()) + if(!clientModel->inInitialBlockDownload()) { // On incoming transaction, make an info balloon // Unless the initial block download is in progress, to prevent balloon-spam @@ -397,7 +449,8 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int QString address = ttm->index(start, TransactionTableModel::ToAddress, parent) .data().toString(); - trayIcon->showMessage(tr("Incoming transaction"), + 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" + @@ -406,14 +459,52 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int } } -void BitcoinGUI::gotoOverviewTab() +void BitcoinGUI::gotoOverviewPage() { overviewAction->setChecked(true); centralWidget->setCurrentWidget(overviewPage); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); } -void BitcoinGUI::gotoHistoryTab() +void BitcoinGUI::gotoHistoryPage() { historyAction->setChecked(true); centralWidget->setCurrentWidget(transactionsPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoAddressBookPage() +{ + addressBookAction->setChecked(true); + centralWidget->setCurrentWidget(addressBookPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoReceiveCoinsPage() +{ + receiveCoinsAction->setChecked(true); + centralWidget->setCurrentWidget(receiveCoinsPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoSendCoinsPage() +{ + sendCoinsAction->setChecked(true); + sendCoinsPage->clear(); + centralWidget->setCurrentWidget(sendCoinsPage); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); } +