X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fbitcoingui.cpp;h=fbab51bd6bb366d97d1546831e99a7cbaed9584c;hb=d52a0f3bca2c8df8360308b062185d803e34f0d9;hp=3a24c76ab4eff53983133ec877760ad7a8c814fa;hpb=249300aebe682dc1a7398794b14f0d6ebde0aee7;p=novacoin.git diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 3a24c76..fbab51b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -10,12 +10,14 @@ #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" +#include "walletmodel.h" #include "guiutil.h" #include "editaddressdialog.h" #include "optionsmodel.h" #include "transactiondescdialog.h" - -#include "main.h" +#include "addresstablemodel.h" +#include "transactionview.h" +#include "overviewpage.h" #include #include @@ -24,40 +26,40 @@ #include #include #include -#include #include #include #include -#include #include #include -#include #include -#include -#include #include +#include +#include #include #include BitcoinGUI::BitcoinGUI(QWidget *parent): - QMainWindow(parent), trayIcon(0) + QMainWindow(parent), + clientModel(0), + walletModel(0), + trayIcon(0) { resize(850, 550); - setWindowTitle(tr("Bitcoin")); + setWindowTitle(tr("Bitcoin Wallet")); setWindowIcon(QIcon(":icons/bitcoin")); createActions(); // Menus QMenu *file = menuBar()->addMenu("&File"); - file->addAction(sendcoins); + file->addAction(sendCoins); + file->addAction(receiveCoins); file->addSeparator(); file->addAction(quit); QMenu *settings = menuBar()->addMenu("&Settings"); - settings->addAction(receivingAddresses); settings->addAction(options); QMenu *help = menuBar()->addMenu("&Help"); @@ -66,139 +68,157 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): // Toolbar QToolBar *toolbar = addToolBar("Main toolbar"); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - toolbar->addAction(sendcoins); + toolbar->addAction(overviewAction); + toolbar->addAction(historyAction); + toolbar->addSeparator(); + toolbar->addAction(sendCoins); + toolbar->addAction(receiveCoins); toolbar->addAction(addressbook); - // Address:
: New... : Paste to clipboard - QHBoxLayout *hbox_address = new QHBoxLayout(); - hbox_address->addWidget(new QLabel(tr("Your Bitcoin Address:"))); - address = new QLineEdit(); - address->setReadOnly(true); - address->setFont(GUIUtil::bitcoinAddressFont()); - address->setToolTip(tr("Your current default receiving address")); - hbox_address->addWidget(address); - - QPushButton *button_new = new QPushButton(tr("&New...")); - button_new->setToolTip(tr("Create new receiving address")); - QPushButton *button_clipboard = new QPushButton(tr("&Copy to clipboard")); - button_clipboard->setToolTip(tr("Copy current receiving address to the system clipboard")); - hbox_address->addWidget(button_new); - hbox_address->addWidget(button_clipboard); - - // Balance: - QHBoxLayout *hbox_balance = new QHBoxLayout(); - hbox_balance->addWidget(new QLabel(tr("Balance:"))); - hbox_balance->addSpacing(5);/* Add some spacing between the label and the text */ - - labelBalance = new QLabel(); - labelBalance->setFont(QFont("Monospace")); - labelBalance->setToolTip(tr("Your current balance")); - hbox_balance->addWidget(labelBalance); - hbox_balance->addStretch(1); - + overviewPage = new OverviewPage(); + QVBoxLayout *vbox = new QVBoxLayout(); - vbox->addLayout(hbox_address); - vbox->addLayout(hbox_balance); - vbox->addWidget(createTabs()); + transactionView = new TransactionView(this); + connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(transactionDetails(const QModelIndex&))); + vbox->addWidget(transactionView); - QWidget *centralwidget = new QWidget(this); - centralwidget->setLayout(vbox); - setCentralWidget(centralwidget); + transactionsPage = new QWidget(this); + transactionsPage->setLayout(vbox); + + centralWidget = new QStackedWidget(this); + centralWidget->addWidget(overviewPage); + centralWidget->addWidget(transactionsPage); + setCentralWidget(centralWidget); // Create status bar statusBar(); - + labelConnections = new QLabel(); labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelConnections->setMinimumWidth(130); + labelConnections->setMinimumWidth(150); labelConnections->setToolTip(tr("Number of connections to other clients")); - + labelBlocks = new QLabel(); labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken); labelBlocks->setMinimumWidth(130); labelBlocks->setToolTip(tr("Number of blocks in the block chain")); - labelTransactions = new QLabel(); - labelTransactions->setFrameStyle(QFrame::Panel | QFrame::Sunken); - labelTransactions->setMinimumWidth(130); - labelTransactions->setToolTip(tr("Number of transactions in your wallet")); + // Progress bar for blocks download + progressBarLabel = new QLabel(tr("Synchronizing with network...")); + progressBarLabel->setVisible(false); + progressBar = new QProgressBar(); + progressBar->setToolTip(tr("Block chain synchronization in progress")); + progressBar->setVisible(false); + statusBar()->addWidget(progressBarLabel); + statusBar()->addWidget(progressBar); statusBar()->addPermanentWidget(labelConnections); statusBar()->addPermanentWidget(labelBlocks); - statusBar()->addPermanentWidget(labelTransactions); - - // Action bindings - connect(button_new, SIGNAL(clicked()), this, SLOT(newAddressClicked())); - connect(button_clipboard, SIGNAL(clicked()), this, SLOT(copyClipboardClicked())); createTrayIcon(); + + gotoOverviewTab(); } 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")); + 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")); - receivingAddresses = new QAction(QIcon(":/icons/receiving-addresses"), tr("Your &Receiving Addresses..."), this); - receivingAddresses->setToolTip(tr("Show the list of receiving addresses and edit their labels")); + 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(sendCoins, SIGNAL(triggered()), this, SLOT(sendCoinsClicked())); connect(addressbook, SIGNAL(triggered()), this, SLOT(addressbookClicked())); - connect(receivingAddresses, SIGNAL(triggered()), this, SLOT(receivingAddressesClicked())); + 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())); } -void BitcoinGUI::setModel(ClientModel *model) +void BitcoinGUI::setClientModel(ClientModel *clientModel) { - this->model = model; + this->clientModel = clientModel; + + if(clientModel->isTestNet()) + { + QString title_testnet = tr("Bitcoin Wallet [testnet]"); + setWindowTitle(title_testnet); + setWindowIcon(QIcon(":icons/bitcoin_testnet")); + if(trayIcon) + { + trayIcon->setToolTip(title_testnet); + trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); + } + } // Keep up to date with client - setBalance(model->getBalance()); - connect(model, SIGNAL(balanceChanged(qint64)), this, SLOT(setBalance(qint64))); + setNumConnections(clientModel->getNumConnections()); + connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumConnections(model->getNumConnections()); - connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + setNumBlocks(clientModel->getNumBlocks()); + connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); - setNumTransactions(model->getNumTransactions()); - connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int))); + // Report errors from network/worker thread + connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); +} - setNumBlocks(model->getNumBlocks()); - connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); +void BitcoinGUI::setWalletModel(WalletModel *walletModel) +{ + this->walletModel = walletModel; - setAddress(model->getAddress()); - connect(model, SIGNAL(addressChanged(QString)), this, SLOT(setAddress(QString))); + // Keep up to date with wallet + setBalance(walletModel->getBalance()); + connect(walletModel, SIGNAL(balanceChanged(qint64)), this, SLOT(setBalance(qint64))); - // Report errors from network/worker thread - connect(model, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); + 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 - setTabsModel(model->getTransactionTableModel()); + transactionView->setModel(walletModel->getTransactionTableModel()); + + // Balloon popup for new transaction + connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(incomingTransaction(const QModelIndex &, int, int))); } void BitcoinGUI::createTrayIcon() { QMenu *trayIconMenu = new QMenu(this); trayIconMenu->addAction(openBitcoin); - trayIconMenu->addAction(sendcoins); + trayIconMenu->addAction(sendCoins); trayIconMenu->addAction(options); trayIconMenu->addSeparator(); trayIconMenu->addAction(quit); trayIcon = new QSystemTrayIcon(this); trayIcon->setContextMenu(trayIconMenu); + trayIcon->setToolTip("Bitcoin client"); trayIcon->setIcon(QIcon(":/icons/toolbar")); connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); @@ -214,87 +234,25 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) } } -QWidget *BitcoinGUI::createTabs() -{ - QStringList tab_labels; - tab_labels << tr("All transactions") - << tr("Sent/Received") - << tr("Sent") - << tr("Received"); - - QTabWidget *tabs = new QTabWidget(this); - for(int i = 0; i < tab_labels.size(); ++i) - { - QTableView *view = new QTableView(this); - tabs->addTab(view, tab_labels.at(i)); - - connect(view, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(transactionDetails(const QModelIndex&))); - transactionViews.append(view); - } - - return tabs; -} - -void BitcoinGUI::setTabsModel(QAbstractItemModel *transaction_model) -{ - QStringList tab_filters; - tab_filters << "^." - << "^["+TransactionTableModel::Sent+TransactionTableModel::Received+"]" - << "^["+TransactionTableModel::Sent+"]" - << "^["+TransactionTableModel::Received+"]"; - - for(int i = 0; i < transactionViews.size(); ++i) - { - QSortFilterProxyModel *proxy_model = new QSortFilterProxyModel(this); - proxy_model->setSourceModel(transaction_model); - proxy_model->setDynamicSortFilter(true); - proxy_model->setFilterRole(TransactionTableModel::TypeRole); - proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i))); - proxy_model->setSortRole(Qt::EditRole); - - QTableView *transaction_table = transactionViews.at(i); - transaction_table->setModel(proxy_model); - transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows); - transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection); - transaction_table->setSortingEnabled(true); - transaction_table->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder); - transaction_table->verticalHeader()->hide(); - - transaction_table->horizontalHeader()->resizeSection( - TransactionTableModel::Status, 145); - transaction_table->horizontalHeader()->resizeSection( - TransactionTableModel::Date, 120); - transaction_table->horizontalHeader()->setResizeMode( - TransactionTableModel::Description, QHeaderView::Stretch); - transaction_table->horizontalHeader()->resizeSection( - TransactionTableModel::Debit, 79); - transaction_table->horizontalHeader()->resizeSection( - TransactionTableModel::Credit, 79); - } - - connect(transaction_model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(incomingTransaction(const QModelIndex &, int, int))); -} - -void BitcoinGUI::sendcoinsClicked() +void BitcoinGUI::sendCoinsClicked() { SendCoinsDialog dlg; - dlg.setModel(model); + dlg.setModel(walletModel); dlg.exec(); } void BitcoinGUI::addressbookClicked() { - AddressBookDialog dlg; - dlg.setModel(model->getAddressTableModel()); + AddressBookDialog dlg(AddressBookDialog::ForEditing); + dlg.setModel(walletModel->getAddressTableModel()); dlg.setTab(AddressBookDialog::SendingTab); dlg.exec(); } -void BitcoinGUI::receivingAddressesClicked() +void BitcoinGUI::receiveCoinsClicked() { - AddressBookDialog dlg; - dlg.setModel(model->getAddressTableModel()); + AddressBookDialog dlg(AddressBookDialog::ForEditing); + dlg.setModel(walletModel->getAddressTableModel()); dlg.setTab(AddressBookDialog::ReceivingTab); dlg.exec(); } @@ -302,60 +260,59 @@ void BitcoinGUI::receivingAddressesClicked() void BitcoinGUI::optionsClicked() { OptionsDialog dlg; - dlg.setModel(model->getOptionsModel()); + dlg.setModel(clientModel->getOptionsModel()); dlg.exec(); } void BitcoinGUI::aboutClicked() { AboutDialog dlg; + dlg.setModel(clientModel); dlg.exec(); } -void BitcoinGUI::newAddressClicked() -{ - EditAddressDialog dlg(EditAddressDialog::NewReceivingAddress); - dlg.setModel(model->getAddressTableModel()); - if(dlg.exec()) - { - QString newAddress = dlg.saveCurrentRow(); - // Set returned address as new default addres - if(!newAddress.isEmpty()) - { - model->setAddress(newAddress); - } - } -} - -void BitcoinGUI::copyClipboardClicked() -{ - // Copy text in address to clipboard - QApplication::clipboard()->setText(address->text()); -} - void BitcoinGUI::setBalance(qint64 balance) { - labelBalance->setText(QString::fromStdString(FormatMoney(balance))); -} - -void BitcoinGUI::setAddress(const QString &addr) -{ - address->setText(addr); + overviewPage->setBalance(balance); } void BitcoinGUI::setNumConnections(int count) { - labelConnections->setText(QLocale::system().toString(count)+" "+tr("connections(s)", "", 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; + } + labelConnections->setTextFormat(Qt::RichText); + labelConnections->setText(" " + tr("%n connection(s)", "", count)); } void BitcoinGUI::setNumBlocks(int count) { - labelBlocks->setText(QLocale::system().toString(count)+" "+tr("block(s)", "", count)); + int total = clientModel->getTotalBlocksEstimate(); + if(count < total) + { + progressBarLabel->setVisible(true); + progressBar->setVisible(true); + progressBar->setMaximum(total); + progressBar->setValue(count); + } + else + { + progressBarLabel->setVisible(false); + progressBar->setVisible(false); + } + + labelBlocks->setText(tr("%n block(s)", "", count)); } void BitcoinGUI::setNumTransactions(int count) { - labelTransactions->setText(QLocale::system().toString(count)+" "+tr("transaction(s)", "", count)); + overviewPage->setNumTransactions(count); } void BitcoinGUI::error(const QString &title, const QString &message) @@ -379,7 +336,7 @@ void BitcoinGUI::changeEvent(QEvent *e) { if (e->type() == QEvent::WindowStateChange) { - if(model->getOptionsModel()->getMinimizeToTray()) + if(clientModel->getOptionsModel()->getMinimizeToTray()) { if (isMinimized()) { @@ -397,8 +354,8 @@ void BitcoinGUI::changeEvent(QEvent *e) void BitcoinGUI::closeEvent(QCloseEvent *event) { - if(!model->getOptionsModel()->getMinimizeToTray() && - !model->getOptionsModel()->getMinimizeOnClose()) + if(!clientModel->getOptionsModel()->getMinimizeToTray() && + !clientModel->getOptionsModel()->getMinimizeOnClose()) { qApp->quit(); } @@ -410,7 +367,7 @@ 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(QString::fromStdString(FormatMoney(nFeeRequired))); + "Do you want to pay the fee?").arg(GUIUtil::formatMoney(nFeeRequired)); QMessageBox::StandardButton retval = QMessageBox::question( this, tr("Sending..."), strMessage, QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); @@ -419,30 +376,44 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) void BitcoinGUI::transactionDetails(const QModelIndex& idx) { - /* A transaction is doubleclicked */ + // A transaction is doubleclicked TransactionDescDialog dlg(idx); dlg.exec(); } void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end) { - TransactionTableModel *ttm = model->getTransactionTableModel(); - qint64 credit = ttm->index(start, TransactionTableModel::Credit, parent) + TransactionTableModel *ttm = walletModel->getTransactionTableModel(); + qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent) .data(Qt::EditRole).toULongLong(); - qint64 debit = ttm->index(start, TransactionTableModel::Debit, parent) - .data(Qt::EditRole).toULongLong(); - if((credit+debit)>0) + if(amount>0 && !clientModel->inInitialBlockDownload()) { - /* On incoming transaction, make an info balloon */ + // On incoming 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(); - QString description = ttm->index(start, TransactionTableModel::Description, parent) + QString type = ttm->index(start, TransactionTableModel::Type, parent) + .data().toString(); + QString address = ttm->index(start, TransactionTableModel::ToAddress, parent) .data().toString(); trayIcon->showMessage(tr("Incoming transaction"), - "Date: " + date + "\n" + - "Amount: " + QString::fromStdString(FormatMoney(credit+debit, true)) + "\n" + - description, + tr("Date: ") + date + "\n" + + tr("Amount: ") + GUIUtil::formatMoney(amount, true) + "\n" + + tr("Type: ") + type + "\n" + + tr("Address: ") + address + "\n", QSystemTrayIcon::Information); } } + +void BitcoinGUI::gotoOverviewTab() +{ + overviewAction->setChecked(true); + centralWidget->setCurrentWidget(overviewPage); +} + +void BitcoinGUI::gotoHistoryTab() +{ + historyAction->setChecked(true); + centralWidget->setCurrentWidget(transactionsPage); +}