Add robustness against null models
authorWladimir J. van der Laan <laanwj@gmail.com>
Tue, 8 Nov 2011 20:18:36 +0000 (21:18 +0100)
committerWladimir J. van der Laan <laanwj@gmail.com>
Tue, 8 Nov 2011 20:18:36 +0000 (21:18 +0100)
src/qt/aboutdialog.cpp
src/qt/addressbookpage.cpp
src/qt/addressbookpage.h
src/qt/askpassphrasedialog.cpp
src/qt/bitcoingui.cpp
src/qt/csvmodelwriter.cpp
src/qt/editaddressdialog.cpp
src/qt/overviewpage.cpp
src/qt/sendcoinsdialog.cpp
src/qt/sendcoinsentry.cpp
src/qt/transactionview.cpp

index 13d263b..a3aa6de 100644 (file)
@@ -12,7 +12,10 @@ AboutDialog::AboutDialog(QWidget *parent) :
 
 void AboutDialog::setModel(ClientModel *model)
 {
-    ui->versionLabel->setText(model->formatFullVersion());
+    if(model)
+    {
+        ui->versionLabel->setText(model->formatFullVersion());
+    }
 }
 
 AboutDialog::~AboutDialog()
index 6be59a0..0a147c9 100644 (file)
@@ -57,6 +57,8 @@ AddressBookPage::~AddressBookPage()
 void AddressBookPage::setModel(AddressTableModel *model)
 {
     this->model = model;
+    if(!model)
+        return;
     // Refresh list from core
     model->updateList();
 
@@ -96,16 +98,13 @@ void AddressBookPage::setModel(AddressTableModel *model)
     selectionChanged();
 }
 
-QTableView *AddressBookPage::getCurrentTable()
-{
-    return ui->tableView;
-}
-
 void AddressBookPage::on_copyToClipboard_clicked()
 {
     // Copy currently selected address to clipboard
     //   (or nothing, if nothing selected)
-    QTableView *table = getCurrentTable();
+    QTableView *table = ui->tableView;
+    if(!table->selectionModel())
+        return;
     QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
 
     foreach (QModelIndex index, indexes)
@@ -117,6 +116,8 @@ void AddressBookPage::on_copyToClipboard_clicked()
 
 void AddressBookPage::on_newAddressButton_clicked()
 {
+    if(!model)
+        return;
     EditAddressDialog dlg(
             tab == SendingTab ?
             EditAddressDialog::NewSendingAddress :
@@ -139,7 +140,9 @@ void AddressBookPage::on_newAddressButton_clicked()
 
 void AddressBookPage::on_deleteButton_clicked()
 {
-    QTableView *table = getCurrentTable();
+    QTableView *table = ui->tableView;
+    if(!table->selectionModel())
+        return;
     QModelIndexList indexes = table->selectionModel()->selectedRows();
     if(!indexes.isEmpty())
     {
@@ -150,7 +153,9 @@ void AddressBookPage::on_deleteButton_clicked()
 void AddressBookPage::selectionChanged()
 {
     // Set button states based on selected tab and selection
-    QTableView *table = getCurrentTable();
+    QTableView *table = ui->tableView;
+    if(!table->selectionModel())
+        return;
 
     if(table->selectionModel()->hasSelection())
     {
@@ -174,12 +179,14 @@ void AddressBookPage::selectionChanged()
 
 void AddressBookPage::done(int retval)
 {
+    QTableView *table = ui->tableView;
+    if(!table->selectionModel() || !table->model())
+        return;
     // When this is a tab/widget and not a model dialog, ignore "done"
     if(mode == ForEditing)
         return;
 
     // Figure out which address was selected, and return it
-    QTableView *table = getCurrentTable();
     QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
 
     foreach (QModelIndex index, indexes)
index 53c7728..ef64d17 100644 (file)
@@ -47,8 +47,6 @@ private:
     QString returnValue;
     QSortFilterProxyModel *proxyModel;
 
-    QTableView *getCurrentTable();
-
 private slots:
     void on_deleteButton_clicked();
     void on_newAddressButton_clicked();
index a297513..89cdf43 100644 (file)
@@ -72,6 +72,8 @@ void AskPassphraseDialog::setModel(WalletModel *model)
 void AskPassphraseDialog::accept()
 {
     std::string oldpass, newpass1, newpass2;
+    if(!model)
+        return;
     // TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely
     oldpass.reserve(MAX_PASSPHRASE_SIZE);
     newpass1.reserve(MAX_PASSPHRASE_SIZE);
index b9995fd..5ae3ce3 100644 (file)
@@ -267,58 +267,62 @@ void BitcoinGUI::createToolBars()
 void BitcoinGUI::setClientModel(ClientModel *clientModel)
 {
     this->clientModel = clientModel;
-
-    if(clientModel->isTestNet())
+    if(clientModel)
     {
-        QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
-        setWindowTitle(title_testnet);
+        if(clientModel->isTestNet())
+        {
+            QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
+            setWindowTitle(title_testnet);
 #ifndef Q_WS_MAC
-        setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+            setWindowIcon(QIcon(":icons/bitcoin_testnet"));
 #else
-        MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
+            MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
 #endif
-        if(trayIcon)
-        {
-            trayIcon->setToolTip(title_testnet);
-            trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
+            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)));
+        setEncryptionStatus(walletModel->getEncryptionStatus());
+        connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
 
-    // Balloon popup for new transaction
-    connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
-            this, SLOT(incomingTransaction(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()));
+        // Ask for passphrase if needed
+        connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
+    }
 }
 
 void BitcoinGUI::createTrayIcon()
@@ -369,6 +373,8 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
 
 void BitcoinGUI::optionsClicked()
 {
+    if(!clientModel || !clientModel->getOptionsModel())
+        return;
     OptionsDialog dlg;
     dlg.setModel(clientModel->getOptionsModel());
     dlg.exec();
@@ -398,6 +404,8 @@ void BitcoinGUI::setNumConnections(int count)
 
 void BitcoinGUI::setNumBlocks(int count)
 {
+    if(!clientModel)
+        return;
     int initTotal = clientModel->getNumBlocksAtStartup();
     int total = clientModel->getNumBlocksOfPeers();
     QString tooltip;
@@ -492,13 +500,16 @@ void BitcoinGUI::changeEvent(QEvent *e)
 
 void BitcoinGUI::closeEvent(QCloseEvent *event)
 {
-#ifndef Q_WS_MAC // Ignored on Mac
-    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);
 }
 
@@ -517,6 +528,8 @@ 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();
@@ -654,6 +667,8 @@ void BitcoinGUI::setEncryptionStatus(int status)
 
 void BitcoinGUI::encryptWallet(bool status)
 {
+    if(!walletModel)
+        return;
     AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt:
                                      AskPassphraseDialog::Decrypt, this);
     dlg.setModel(walletModel);
@@ -671,6 +686,8 @@ void BitcoinGUI::changePassphrase()
 
 void BitcoinGUI::unlockWallet()
 {
+    if(!walletModel)
+        return;
     // Unlock wallet when requested by wallet model
     if(walletModel->getEncryptionStatus() == WalletModel::Locked)
     {
index 62c0b94..4b21b8c 100644 (file)
@@ -48,7 +48,11 @@ bool CSVModelWriter::write()
         return false;
     QTextStream out(&file);
 
-    int numRows = model->rowCount();
+    int numRows = 0;
+    if(model)
+    {
+        numRows = model->rowCount();
+    }
 
     // Header row
     for(int i=0; i<columns.size(); ++i)
index 457e8cf..8cc3c85 100644 (file)
@@ -56,6 +56,8 @@ void EditAddressDialog::loadRow(int row)
 
 bool EditAddressDialog::saveCurrentRow()
 {
+    if(!model)
+        return false;
     switch(mode)
     {
     case NewReceivingAddress:
@@ -78,6 +80,8 @@ bool EditAddressDialog::saveCurrentRow()
 
 void EditAddressDialog::accept()
 {
+    if(!model)
+        return;
     if(!saveCurrentRow())
     {
         switch(model->getEditStatus())
index 6dedde0..fe09871 100644 (file)
@@ -143,30 +143,34 @@ void OverviewPage::setNumTransactions(int count)
 void OverviewPage::setModel(WalletModel *model)
 {
     this->model = model;
+    if(model)
+    {
+        // Set up transaction list
+        TransactionFilterProxy *filter = new TransactionFilterProxy();
+        filter->setSourceModel(model->getTransactionTableModel());
+        filter->setLimit(NUM_ITEMS);
+        filter->setDynamicSortFilter(true);
+        filter->setSortRole(Qt::EditRole);
+        filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
 
-    // Set up transaction list
-    TransactionFilterProxy *filter = new TransactionFilterProxy();
-    filter->setSourceModel(model->getTransactionTableModel());
-    filter->setLimit(NUM_ITEMS);
-    filter->setDynamicSortFilter(true);
-    filter->setSortRole(Qt::EditRole);
-    filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
-
-    ui->listTransactions->setModel(filter);
-    ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
+        ui->listTransactions->setModel(filter);
+        ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
 
-    // Keep up to date with wallet
-    setBalance(model->getBalance(), model->getUnconfirmedBalance());
-    connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+        // Keep up to date with wallet
+        setBalance(model->getBalance(), model->getUnconfirmedBalance());
+        connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
 
-    setNumTransactions(model->getNumTransactions());
-    connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int)));
+        setNumTransactions(model->getNumTransactions());
+        connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int)));
 
-    connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged()));
+        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged()));
+    }
 }
 
 void OverviewPage::displayUnitChanged()
 {
+    if(!model || !model->getOptionsModel())
+        return;
     if(currentBalance != -1)
         setBalance(currentBalance, currentUnconfirmedBalance);
 
index 719cc51..762f27d 100644 (file)
@@ -43,9 +43,11 @@ void SendCoinsDialog::setModel(WalletModel *model)
             entry->setModel(model);
         }
     }
-
-    setBalance(model->getBalance(), model->getUnconfirmedBalance());
-    connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+    if(model)
+    {
+        setBalance(model->getBalance(), model->getUnconfirmedBalance());
+        connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+    }
 }
 
 SendCoinsDialog::~SendCoinsDialog()
@@ -57,6 +59,10 @@ void SendCoinsDialog::on_sendButton_clicked()
 {
     QList<SendCoinsRecipient> recipients;
     bool valid = true;
+
+    if(!model)
+        return;
+
     for(int i = 0; i < ui->entries->count(); ++i)
     {
         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
@@ -255,6 +261,9 @@ void SendCoinsDialog::handleURL(const QUrl *url)
 void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance)
 {
     Q_UNUSED(unconfirmedBalance);
+    if(!model || !model->getOptionsModel())
+        return;
+
     int unit = model->getOptionsModel()->getDisplayUnit();
     ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
 }
index 1802095..23b11cc 100644 (file)
@@ -44,6 +44,8 @@ void SendCoinsEntry::on_pasteButton_clicked()
 
 void SendCoinsEntry::on_addressBookButton_clicked()
 {
+    if(!model)
+        return;
     AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
     dlg.setModel(model->getAddressTableModel());
     if(dlg.exec())
@@ -55,6 +57,8 @@ void SendCoinsEntry::on_addressBookButton_clicked()
 
 void SendCoinsEntry::on_payTo_textChanged(const QString &address)
 {
+    if(!model)
+        return;
     ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));
 }
 
@@ -74,7 +78,7 @@ void SendCoinsEntry::clear()
     ui->addAsLabel->clear();
     ui->payAmount->clear();
     ui->payTo->setFocus();
-    if(model)
+    if(model && model->getOptionsModel())
     {
         ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
     }
index d39227c..2dcbf1e 100644 (file)
@@ -155,36 +155,39 @@ TransactionView::TransactionView(QWidget *parent) :
 void TransactionView::setModel(WalletModel *model)
 {
     this->model = model;
-
-    transactionProxyModel = new TransactionFilterProxy(this);
-    transactionProxyModel->setSourceModel(model->getTransactionTableModel());
-    transactionProxyModel->setDynamicSortFilter(true);
-
-    transactionProxyModel->setSortRole(Qt::EditRole);
-
-    transactionView->setModel(transactionProxyModel);
-    transactionView->setAlternatingRowColors(true);
-    transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
-    transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
-    transactionView->setSortingEnabled(true);
-    transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
-    transactionView->verticalHeader()->hide();
-
-    transactionView->horizontalHeader()->resizeSection(
-            TransactionTableModel::Status, 23);
-    transactionView->horizontalHeader()->resizeSection(
-            TransactionTableModel::Date, 120);
-    transactionView->horizontalHeader()->resizeSection(
-            TransactionTableModel::Type, 120);
-    transactionView->horizontalHeader()->setResizeMode(
-            TransactionTableModel::ToAddress, QHeaderView::Stretch);
-    transactionView->horizontalHeader()->resizeSection(
-            TransactionTableModel::Amount, 100);
-
+    if(model)
+    {
+        transactionProxyModel = new TransactionFilterProxy(this);
+        transactionProxyModel->setSourceModel(model->getTransactionTableModel());
+        transactionProxyModel->setDynamicSortFilter(true);
+
+        transactionProxyModel->setSortRole(Qt::EditRole);
+
+        transactionView->setModel(transactionProxyModel);
+        transactionView->setAlternatingRowColors(true);
+        transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
+        transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+        transactionView->setSortingEnabled(true);
+        transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
+        transactionView->verticalHeader()->hide();
+
+        transactionView->horizontalHeader()->resizeSection(
+                TransactionTableModel::Status, 23);
+        transactionView->horizontalHeader()->resizeSection(
+                TransactionTableModel::Date, 120);
+        transactionView->horizontalHeader()->resizeSection(
+                TransactionTableModel::Type, 120);
+        transactionView->horizontalHeader()->setResizeMode(
+                TransactionTableModel::ToAddress, QHeaderView::Stretch);
+        transactionView->horizontalHeader()->resizeSection(
+                TransactionTableModel::Amount, 100);
+    }
 }
 
 void TransactionView::chooseDate(int idx)
 {
+    if(!transactionProxyModel)
+        return;
     QDate current = QDate::currentDate();
     dateRangeWidget->setVisible(false);
     switch(dateWidget->itemData(idx).toInt())
@@ -231,17 +234,23 @@ void TransactionView::chooseDate(int idx)
 
 void TransactionView::chooseType(int idx)
 {
+    if(!transactionProxyModel)
+        return;
     transactionProxyModel->setTypeFilter(
         typeWidget->itemData(idx).toInt());
 }
 
 void TransactionView::changedPrefix(const QString &prefix)
 {
+    if(!transactionProxyModel)
+        return;
     transactionProxyModel->setAddressPrefix(prefix);
 }
 
 void TransactionView::changedAmount(const QString &amount)
 {
+    if(!transactionProxyModel)
+        return;
     qint64 amount_parsed = 0;
     if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed))
     {
@@ -294,6 +303,8 @@ void TransactionView::contextualMenu(const QPoint &point)
 
 void TransactionView::copyAddress()
 {
+    if(!transactionView->selectionModel())
+        return;
     QModelIndexList selection = transactionView->selectionModel()->selectedRows();
     if(!selection.isEmpty())
     {
@@ -303,6 +314,8 @@ void TransactionView::copyAddress()
 
 void TransactionView::copyLabel()
 {
+    if(!transactionView->selectionModel())
+        return;
     QModelIndexList selection = transactionView->selectionModel()->selectedRows();
     if(!selection.isEmpty())
     {
@@ -312,10 +325,14 @@ void TransactionView::copyLabel()
 
 void TransactionView::editLabel()
 {
+    if(!transactionView->selectionModel() ||!model)
+        return;
     QModelIndexList selection = transactionView->selectionModel()->selectedRows();
     if(!selection.isEmpty())
     {
         AddressTableModel *addressBook = model->getAddressTableModel();
+        if(!addressBook)
+            return;
         QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
         if(address.isEmpty())
         {
@@ -354,6 +371,8 @@ void TransactionView::editLabel()
 
 void TransactionView::showDetails()
 {
+    if(!transactionView->selectionModel())
+        return;
     QModelIndexList selection = transactionView->selectionModel()->selectedRows();
     if(!selection.isEmpty())
     {
@@ -400,6 +419,8 @@ QWidget *TransactionView::createDateRangeWidget()
 
 void TransactionView::dateRangeChanged()
 {
+    if(!transactionProxyModel)
+        return;
     transactionProxyModel->setDateRange(
             QDateTime(dateFrom->date()),
             QDateTime(dateTo->date()).addDays(1));