mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-17 18:40:09 +00:00
Merge #9190: qt: Plug many memory leaks
ed998ea qt: Avoid OpenSSL certstore-related memory leak (Wladimir J. van der Laan) 5204598 qt: Avoid shutdownwindow-related memory leak (Wladimir J. van der Laan) e4f126a qt: Avoid splash-screen related memory leak (Wladimir J. van der Laan) 693384e qt: Prevent thread/memory leak on exiting RPCConsole (Wladimir J. van der Laan) 47db075 qt: Plug many memory leaks (Wladimir J. van der Laan)
This commit is contained in:
commit
db5e22e053
@ -83,7 +83,7 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
|
|||||||
deleteAction = new QAction(ui->deleteAddress->text(), this);
|
deleteAction = new QAction(ui->deleteAddress->text(), this);
|
||||||
|
|
||||||
// Build context menu
|
// Build context menu
|
||||||
contextMenu = new QMenu();
|
contextMenu = new QMenu(this);
|
||||||
contextMenu->addAction(copyAddressAction);
|
contextMenu->addAction(copyAddressAction);
|
||||||
contextMenu->addAction(copyLabelAction);
|
contextMenu->addAction(copyLabelAction);
|
||||||
contextMenu->addAction(editAction);
|
contextMenu->addAction(editAction);
|
||||||
|
@ -87,7 +87,7 @@ BanTableModel::BanTableModel(ClientModel *parent) :
|
|||||||
clientModel(parent)
|
clientModel(parent)
|
||||||
{
|
{
|
||||||
columns << tr("IP/Netmask") << tr("Banned Until");
|
columns << tr("IP/Netmask") << tr("Banned Until");
|
||||||
priv = new BanTablePriv();
|
priv.reset(new BanTablePriv());
|
||||||
// default to unsorted
|
// default to unsorted
|
||||||
priv->sortColumn = -1;
|
priv->sortColumn = -1;
|
||||||
|
|
||||||
@ -95,6 +95,11 @@ BanTableModel::BanTableModel(ClientModel *parent) :
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BanTableModel::~BanTableModel()
|
||||||
|
{
|
||||||
|
// Intentionally left empty
|
||||||
|
}
|
||||||
|
|
||||||
int BanTableModel::rowCount(const QModelIndex &parent) const
|
int BanTableModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
|
@ -40,6 +40,7 @@ class BanTableModel : public QAbstractTableModel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BanTableModel(ClientModel *parent = 0);
|
explicit BanTableModel(ClientModel *parent = 0);
|
||||||
|
~BanTableModel();
|
||||||
void startAutoRefresh();
|
void startAutoRefresh();
|
||||||
void stopAutoRefresh();
|
void stopAutoRefresh();
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ public Q_SLOTS:
|
|||||||
private:
|
private:
|
||||||
ClientModel *clientModel;
|
ClientModel *clientModel;
|
||||||
QStringList columns;
|
QStringList columns;
|
||||||
BanTablePriv *priv;
|
std::unique_ptr<BanTablePriv> priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_QT_BANTABLEMODEL_H
|
#endif // BITCOIN_QT_BANTABLEMODEL_H
|
||||||
|
@ -245,6 +245,7 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
int returnValue;
|
int returnValue;
|
||||||
const PlatformStyle *platformStyle;
|
const PlatformStyle *platformStyle;
|
||||||
|
std::unique_ptr<QWidget> shutdownWindow;
|
||||||
|
|
||||||
void startThread();
|
void startThread();
|
||||||
};
|
};
|
||||||
@ -365,9 +366,8 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
|
|||||||
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
|
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
|
||||||
{
|
{
|
||||||
SplashScreen *splash = new SplashScreen(0, networkStyle);
|
SplashScreen *splash = new SplashScreen(0, networkStyle);
|
||||||
// We don't hold a direct pointer to the splash screen after creation, so use
|
// We don't hold a direct pointer to the splash screen after creation, but the splash
|
||||||
// Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually.
|
// screen will take care of deleting itself when slotFinish happens.
|
||||||
splash->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
splash->show();
|
splash->show();
|
||||||
connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*)));
|
connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*)));
|
||||||
connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close()));
|
connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close()));
|
||||||
@ -409,6 +409,11 @@ void BitcoinApplication::requestInitialize()
|
|||||||
|
|
||||||
void BitcoinApplication::requestShutdown()
|
void BitcoinApplication::requestShutdown()
|
||||||
{
|
{
|
||||||
|
// Show a simple window indicating shutdown status
|
||||||
|
// Do this first as some of the steps may take some time below,
|
||||||
|
// for example the RPC console may still be executing a command.
|
||||||
|
shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window));
|
||||||
|
|
||||||
qDebug() << __func__ << ": Requesting shutdown";
|
qDebug() << __func__ << ": Requesting shutdown";
|
||||||
startThread();
|
startThread();
|
||||||
window->hide();
|
window->hide();
|
||||||
@ -423,9 +428,6 @@ void BitcoinApplication::requestShutdown()
|
|||||||
delete clientModel;
|
delete clientModel;
|
||||||
clientModel = 0;
|
clientModel = 0;
|
||||||
|
|
||||||
// Show a simple window indicating shutdown status
|
|
||||||
ShutdownWindow::showShutdownWindow(window);
|
|
||||||
|
|
||||||
// Request shutdown from core thread
|
// Request shutdown from core thread
|
||||||
Q_EMIT requestedShutdown();
|
Q_EMIT requestedShutdown();
|
||||||
}
|
}
|
||||||
|
@ -511,6 +511,13 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
|||||||
// Disable context menu on tray icon
|
// Disable context menu on tray icon
|
||||||
trayIconMenu->clear();
|
trayIconMenu->clear();
|
||||||
}
|
}
|
||||||
|
// Propagate cleared model to child objects
|
||||||
|
rpcConsole->setClientModel(nullptr);
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
walletFrame->setClientModel(nullptr);
|
||||||
|
#endif // ENABLE_WALLET
|
||||||
|
unitDisplayControl->setOptionsModel(nullptr);
|
||||||
|
connectionsControl->setClientModel(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1191,7 +1198,7 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
|
|||||||
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
|
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
|
||||||
void UnitDisplayStatusBarControl::createContextMenu()
|
void UnitDisplayStatusBarControl::createContextMenu()
|
||||||
{
|
{
|
||||||
menu = new QMenu();
|
menu = new QMenu(this);
|
||||||
Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
|
Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
|
||||||
{
|
{
|
||||||
QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
|
QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
|
||||||
@ -1248,7 +1255,5 @@ void NetworkToggleStatusBarControl::mousePressEvent(QMouseEvent *event)
|
|||||||
/** Lets the control know about the Client Model */
|
/** Lets the control know about the Client Model */
|
||||||
void NetworkToggleStatusBarControl::setClientModel(ClientModel *_clientModel)
|
void NetworkToggleStatusBarControl::setClientModel(ClientModel *_clientModel)
|
||||||
{
|
{
|
||||||
if (_clientModel) {
|
this->clientModel = _clientModel;
|
||||||
this->clientModel = _clientModel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
|
|||||||
unlockAction = new QAction(tr("Unlock unspent"), this); // we need to enable/disable this
|
unlockAction = new QAction(tr("Unlock unspent"), this); // we need to enable/disable this
|
||||||
|
|
||||||
// context menu
|
// context menu
|
||||||
contextMenu = new QMenu();
|
contextMenu = new QMenu(this);
|
||||||
contextMenu->addAction(copyAddressAction);
|
contextMenu->addAction(copyAddressAction);
|
||||||
contextMenu->addAction(copyLabelAction);
|
contextMenu->addAction(copyLabelAction);
|
||||||
contextMenu->addAction(copyAmountAction);
|
contextMenu->addAction(copyAmountAction);
|
||||||
|
@ -585,7 +585,8 @@ void TableViewLastColumnResizingFixer::on_geometriesChanged()
|
|||||||
* Initializes all internal variables and prepares the
|
* Initializes all internal variables and prepares the
|
||||||
* the resize modes of the last 2 columns of the table and
|
* the resize modes of the last 2 columns of the table and
|
||||||
*/
|
*/
|
||||||
TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth) :
|
TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
tableView(table),
|
tableView(table),
|
||||||
lastColumnMinimumWidth(lastColMinimumWidth),
|
lastColumnMinimumWidth(lastColMinimumWidth),
|
||||||
allColumnsMinimumWidth(allColsMinimumWidth)
|
allColumnsMinimumWidth(allColsMinimumWidth)
|
||||||
|
@ -149,7 +149,7 @@ namespace GUIUtil
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth);
|
TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth, QObject *parent);
|
||||||
void stretchColumnWidth(int column);
|
void stretchColumnWidth(int column);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -25,8 +25,8 @@ class TxViewDelegate : public QAbstractItemDelegate
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TxViewDelegate(const PlatformStyle *_platformStyle):
|
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
|
||||||
QAbstractItemDelegate(), unit(BitcoinUnits::BTC),
|
QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
|
||||||
platformStyle(_platformStyle)
|
platformStyle(_platformStyle)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -119,8 +119,7 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
|
|||||||
currentWatchOnlyBalance(-1),
|
currentWatchOnlyBalance(-1),
|
||||||
currentWatchUnconfBalance(-1),
|
currentWatchUnconfBalance(-1),
|
||||||
currentWatchImmatureBalance(-1),
|
currentWatchImmatureBalance(-1),
|
||||||
txdelegate(new TxViewDelegate(platformStyle)),
|
txdelegate(new TxViewDelegate(platformStyle, this))
|
||||||
filter(0)
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -220,7 +219,7 @@ void OverviewPage::setWalletModel(WalletModel *model)
|
|||||||
if(model && model->getOptionsModel())
|
if(model && model->getOptionsModel())
|
||||||
{
|
{
|
||||||
// Set up transaction list
|
// Set up transaction list
|
||||||
filter = new TransactionFilterProxy();
|
filter.reset(new TransactionFilterProxy());
|
||||||
filter->setSourceModel(model->getTransactionTableModel());
|
filter->setSourceModel(model->getTransactionTableModel());
|
||||||
filter->setLimit(NUM_ITEMS);
|
filter->setLimit(NUM_ITEMS);
|
||||||
filter->setDynamicSortFilter(true);
|
filter->setDynamicSortFilter(true);
|
||||||
@ -228,7 +227,7 @@ void OverviewPage::setWalletModel(WalletModel *model)
|
|||||||
filter->setShowInactive(false);
|
filter->setShowInactive(false);
|
||||||
filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
|
filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
|
||||||
|
|
||||||
ui->listTransactions->setModel(filter);
|
ui->listTransactions->setModel(filter.get());
|
||||||
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
|
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
|
||||||
|
|
||||||
// Keep up to date with wallet
|
// Keep up to date with wallet
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "amount.h"
|
#include "amount.h"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class ClientModel;
|
class ClientModel;
|
||||||
class TransactionFilterProxy;
|
class TransactionFilterProxy;
|
||||||
@ -56,7 +57,7 @@ private:
|
|||||||
CAmount currentWatchImmatureBalance;
|
CAmount currentWatchImmatureBalance;
|
||||||
|
|
||||||
TxViewDelegate *txdelegate;
|
TxViewDelegate *txdelegate;
|
||||||
TransactionFilterProxy *filter;
|
std::unique_ptr<TransactionFilterProxy> filter;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void updateDisplayUnit();
|
void updateDisplayUnit();
|
||||||
|
@ -58,14 +58,19 @@ const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest"
|
|||||||
// BIP70 max payment request size in bytes (DoS protection)
|
// BIP70 max payment request size in bytes (DoS protection)
|
||||||
const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
|
const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
|
||||||
|
|
||||||
X509_STORE* PaymentServer::certStore = NULL;
|
struct X509StoreDeleter {
|
||||||
void PaymentServer::freeCertStore()
|
void operator()(X509_STORE* b) {
|
||||||
|
X509_STORE_free(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X509Deleter {
|
||||||
|
void operator()(X509* b) { X509_free(b); }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace // Anon namespace
|
||||||
{
|
{
|
||||||
if (PaymentServer::certStore != NULL)
|
std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
|
||||||
{
|
|
||||||
X509_STORE_free(PaymentServer::certStore);
|
|
||||||
PaymentServer::certStore = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -107,20 +112,15 @@ static void ReportInvalidCertificate(const QSslCertificate& cert)
|
|||||||
//
|
//
|
||||||
void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
||||||
{
|
{
|
||||||
if (PaymentServer::certStore == NULL)
|
|
||||||
atexit(PaymentServer::freeCertStore);
|
|
||||||
else
|
|
||||||
freeCertStore();
|
|
||||||
|
|
||||||
// Unit tests mostly use this, to pass in fake root CAs:
|
// Unit tests mostly use this, to pass in fake root CAs:
|
||||||
if (_store)
|
if (_store)
|
||||||
{
|
{
|
||||||
PaymentServer::certStore = _store;
|
certStore.reset(_store);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal execution, use either -rootcertificates or system certs:
|
// Normal execution, use either -rootcertificates or system certs:
|
||||||
PaymentServer::certStore = X509_STORE_new();
|
certStore.reset(X509_STORE_new());
|
||||||
|
|
||||||
// Note: use "-system-" default here so that users can pass -rootcertificates=""
|
// Note: use "-system-" default here so that users can pass -rootcertificates=""
|
||||||
// and get 'I don't like X.509 certificates, don't trust anybody' behavior:
|
// and get 'I don't like X.509 certificates, don't trust anybody' behavior:
|
||||||
@ -167,11 +167,11 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
|||||||
QByteArray certData = cert.toDer();
|
QByteArray certData = cert.toDer();
|
||||||
const unsigned char *data = (const unsigned char *)certData.data();
|
const unsigned char *data = (const unsigned char *)certData.data();
|
||||||
|
|
||||||
X509* x509 = d2i_X509(0, &data, certData.size());
|
std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
|
||||||
if (x509 && X509_STORE_add_cert(PaymentServer::certStore, x509))
|
if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
|
||||||
{
|
{
|
||||||
// Note: X509_STORE_free will free the X509* objects when
|
// Note: X509_STORE increases the reference count to the X509 object,
|
||||||
// the PaymentServer is destroyed
|
// we still have to release our reference to it.
|
||||||
++nRootCerts;
|
++nRootCerts;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -550,7 +550,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
|
|||||||
recipient.paymentRequest = request;
|
recipient.paymentRequest = request;
|
||||||
recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
|
recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
|
||||||
|
|
||||||
request.getMerchant(PaymentServer::certStore, recipient.authenticatedMerchant);
|
request.getMerchant(certStore.get(), recipient.authenticatedMerchant);
|
||||||
|
|
||||||
QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo();
|
QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo();
|
||||||
QStringList addresses;
|
QStringList addresses;
|
||||||
@ -807,3 +807,8 @@ bool PaymentServer::verifyAmount(const CAmount& requestAmount)
|
|||||||
}
|
}
|
||||||
return fVerified;
|
return fVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X509_STORE* PaymentServer::getCertStore()
|
||||||
|
{
|
||||||
|
return certStore.get();
|
||||||
|
}
|
||||||
|
@ -83,7 +83,7 @@ public:
|
|||||||
static void LoadRootCAs(X509_STORE* store = NULL);
|
static void LoadRootCAs(X509_STORE* store = NULL);
|
||||||
|
|
||||||
// Return certificate store
|
// Return certificate store
|
||||||
static X509_STORE* getCertStore() { return certStore; }
|
static X509_STORE* getCertStore();
|
||||||
|
|
||||||
// OptionsModel is used for getting proxy settings and display unit
|
// OptionsModel is used for getting proxy settings and display unit
|
||||||
void setOptionsModel(OptionsModel *optionsModel);
|
void setOptionsModel(OptionsModel *optionsModel);
|
||||||
@ -140,9 +140,6 @@ private:
|
|||||||
bool saveURIs; // true during startup
|
bool saveURIs; // true during startup
|
||||||
QLocalServer* uriServer;
|
QLocalServer* uriServer;
|
||||||
|
|
||||||
static X509_STORE* certStore; // Trusted root certificates
|
|
||||||
static void freeCertStore();
|
|
||||||
|
|
||||||
QNetworkAccessManager* netManager; // Used to fetch payment requests
|
QNetworkAccessManager* netManager; // Used to fetch payment requests
|
||||||
|
|
||||||
OptionsModel *optionsModel;
|
OptionsModel *optionsModel;
|
||||||
|
@ -114,12 +114,12 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
|
|||||||
timer(0)
|
timer(0)
|
||||||
{
|
{
|
||||||
columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping");
|
columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping");
|
||||||
priv = new PeerTablePriv();
|
priv.reset(new PeerTablePriv());
|
||||||
// default to unsorted
|
// default to unsorted
|
||||||
priv->sortColumn = -1;
|
priv->sortColumn = -1;
|
||||||
|
|
||||||
// set up timer for auto refresh
|
// set up timer for auto refresh
|
||||||
timer = new QTimer();
|
timer = new QTimer(this);
|
||||||
connect(timer, SIGNAL(timeout()), SLOT(refresh()));
|
connect(timer, SIGNAL(timeout()), SLOT(refresh()));
|
||||||
timer->setInterval(MODEL_UPDATE_DELAY);
|
timer->setInterval(MODEL_UPDATE_DELAY);
|
||||||
|
|
||||||
@ -127,6 +127,11 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeerTableModel::~PeerTableModel()
|
||||||
|
{
|
||||||
|
// Intentionally left empty
|
||||||
|
}
|
||||||
|
|
||||||
void PeerTableModel::startAutoRefresh()
|
void PeerTableModel::startAutoRefresh()
|
||||||
{
|
{
|
||||||
timer->start();
|
timer->start();
|
||||||
|
@ -46,6 +46,7 @@ class PeerTableModel : public QAbstractTableModel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PeerTableModel(ClientModel *parent = 0);
|
explicit PeerTableModel(ClientModel *parent = 0);
|
||||||
|
~PeerTableModel();
|
||||||
const CNodeCombinedStats *getNodeStats(int idx);
|
const CNodeCombinedStats *getNodeStats(int idx);
|
||||||
int getRowByNodeId(NodeId nodeid);
|
int getRowByNodeId(NodeId nodeid);
|
||||||
void startAutoRefresh();
|
void startAutoRefresh();
|
||||||
@ -75,7 +76,7 @@ public Q_SLOTS:
|
|||||||
private:
|
private:
|
||||||
ClientModel *clientModel;
|
ClientModel *clientModel;
|
||||||
QStringList columns;
|
QStringList columns;
|
||||||
PeerTablePriv *priv;
|
std::unique_ptr<PeerTablePriv> priv;
|
||||||
QTimer *timer;
|
QTimer *timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::ReceiveCoinsDialog),
|
ui(new Ui::ReceiveCoinsDialog),
|
||||||
|
columnResizingFixer(0),
|
||||||
model(0),
|
model(0),
|
||||||
platformStyle(_platformStyle)
|
platformStyle(_platformStyle)
|
||||||
{
|
{
|
||||||
@ -49,7 +50,7 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid
|
|||||||
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
|
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
|
||||||
|
|
||||||
// context menu
|
// context menu
|
||||||
contextMenu = new QMenu();
|
contextMenu = new QMenu(this);
|
||||||
contextMenu->addAction(copyURIAction);
|
contextMenu->addAction(copyURIAction);
|
||||||
contextMenu->addAction(copyLabelAction);
|
contextMenu->addAction(copyLabelAction);
|
||||||
contextMenu->addAction(copyMessageAction);
|
contextMenu->addAction(copyMessageAction);
|
||||||
@ -91,7 +92,7 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
|
|||||||
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
|
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
|
||||||
SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
|
SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
|
||||||
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
|
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
|
||||||
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH);
|
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
QRImageWidget::QRImageWidget(QWidget *parent):
|
QRImageWidget::QRImageWidget(QWidget *parent):
|
||||||
QLabel(parent), contextMenu(0)
|
QLabel(parent), contextMenu(0)
|
||||||
{
|
{
|
||||||
contextMenu = new QMenu();
|
contextMenu = new QMenu(this);
|
||||||
QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
|
QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
|
||||||
connect(saveImageAction, SIGNAL(triggered()), this, SLOT(saveImage()));
|
connect(saveImageAction, SIGNAL(triggered()), this, SLOT(saveImage()));
|
||||||
contextMenu->addAction(saveImageAction);
|
contextMenu->addAction(saveImageAction);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel *parent) :
|
RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel *parent) :
|
||||||
walletModel(parent)
|
QAbstractTableModel(parent), walletModel(parent)
|
||||||
{
|
{
|
||||||
Q_UNUSED(wallet);
|
Q_UNUSED(wallet);
|
||||||
nReceiveRequestsMaxId = 0;
|
nReceiveRequestsMaxId = 0;
|
||||||
|
@ -382,7 +382,6 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
|
|||||||
// based timer interface
|
// based timer interface
|
||||||
RPCSetTimerInterfaceIfUnset(rpcTimerInterface);
|
RPCSetTimerInterfaceIfUnset(rpcTimerInterface);
|
||||||
|
|
||||||
startExecutor();
|
|
||||||
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
|
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
|
||||||
|
|
||||||
ui->detailWidget->hide();
|
ui->detailWidget->hide();
|
||||||
@ -396,7 +395,6 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
|
|||||||
RPCConsole::~RPCConsole()
|
RPCConsole::~RPCConsole()
|
||||||
{
|
{
|
||||||
GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
|
GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
|
||||||
Q_EMIT stopExecutor();
|
|
||||||
RPCUnsetTimerInterface(rpcTimerInterface);
|
RPCUnsetTimerInterface(rpcTimerInterface);
|
||||||
delete rpcTimerInterface;
|
delete rpcTimerInterface;
|
||||||
delete ui;
|
delete ui;
|
||||||
@ -486,7 +484,7 @@ void RPCConsole::setClientModel(ClientModel *model)
|
|||||||
QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
|
QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
|
||||||
|
|
||||||
// create peer table context menu
|
// create peer table context menu
|
||||||
peersTableContextMenu = new QMenu();
|
peersTableContextMenu = new QMenu(this);
|
||||||
peersTableContextMenu->addAction(disconnectAction);
|
peersTableContextMenu->addAction(disconnectAction);
|
||||||
peersTableContextMenu->addAction(banAction1h);
|
peersTableContextMenu->addAction(banAction1h);
|
||||||
peersTableContextMenu->addAction(banAction24h);
|
peersTableContextMenu->addAction(banAction24h);
|
||||||
@ -534,7 +532,7 @@ void RPCConsole::setClientModel(ClientModel *model)
|
|||||||
QAction* unbanAction = new QAction(tr("&Unban"), this);
|
QAction* unbanAction = new QAction(tr("&Unban"), this);
|
||||||
|
|
||||||
// create ban table context menu
|
// create ban table context menu
|
||||||
banTableContextMenu = new QMenu();
|
banTableContextMenu = new QMenu(this);
|
||||||
banTableContextMenu->addAction(unbanAction);
|
banTableContextMenu->addAction(unbanAction);
|
||||||
|
|
||||||
// ban table context menu signals
|
// ban table context menu signals
|
||||||
@ -565,6 +563,14 @@ void RPCConsole::setClientModel(ClientModel *model)
|
|||||||
autoCompleter = new QCompleter(wordList, this);
|
autoCompleter = new QCompleter(wordList, this);
|
||||||
ui->lineEdit->setCompleter(autoCompleter);
|
ui->lineEdit->setCompleter(autoCompleter);
|
||||||
autoCompleter->popup()->installEventFilter(this);
|
autoCompleter->popup()->installEventFilter(this);
|
||||||
|
// Start thread to execute RPC commands.
|
||||||
|
startExecutor();
|
||||||
|
}
|
||||||
|
if (!model) {
|
||||||
|
// Client model is being set to 0, this means shutdown() is about to be called.
|
||||||
|
// Make sure we clean up the executor thread
|
||||||
|
Q_EMIT stopExecutor();
|
||||||
|
thread.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,9 +765,8 @@ void RPCConsole::browseHistory(int offset)
|
|||||||
|
|
||||||
void RPCConsole::startExecutor()
|
void RPCConsole::startExecutor()
|
||||||
{
|
{
|
||||||
QThread *thread = new QThread;
|
|
||||||
RPCExecutor *executor = new RPCExecutor();
|
RPCExecutor *executor = new RPCExecutor();
|
||||||
executor->moveToThread(thread);
|
executor->moveToThread(&thread);
|
||||||
|
|
||||||
// Replies from executor object must go to this object
|
// Replies from executor object must go to this object
|
||||||
connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
|
connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
|
||||||
@ -769,16 +774,15 @@ void RPCConsole::startExecutor()
|
|||||||
connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
|
connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
|
||||||
|
|
||||||
// On stopExecutor signal
|
// On stopExecutor signal
|
||||||
// - queue executor for deletion (in execution thread)
|
|
||||||
// - quit the Qt event loop in the execution thread
|
// - quit the Qt event loop in the execution thread
|
||||||
connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
|
connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit()));
|
||||||
connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
|
// - queue executor for deletion (in execution thread)
|
||||||
// Queue the thread for deletion (in this thread) when it is finished
|
connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
|
||||||
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
connect(&thread, SIGNAL(finished()), this, SLOT(test()), Qt::DirectConnection);
|
||||||
|
|
||||||
// Default implementation of QThread::run() simply spins up an event loop in the thread,
|
// Default implementation of QThread::run() simply spins up an event loop in the thread,
|
||||||
// which is what we want.
|
// which is what we want.
|
||||||
thread->start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCConsole::on_tabWidget_currentChanged(int index)
|
void RPCConsole::on_tabWidget_currentChanged(int index)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
class ClientModel;
|
class ClientModel;
|
||||||
class PlatformStyle;
|
class PlatformStyle;
|
||||||
@ -148,6 +149,7 @@ private:
|
|||||||
QMenu *banTableContextMenu;
|
QMenu *banTableContextMenu;
|
||||||
int consoleFontSize;
|
int consoleFontSize;
|
||||||
QCompleter *autoCompleter;
|
QCompleter *autoCompleter;
|
||||||
|
QThread thread;
|
||||||
|
|
||||||
/** Update UI with latest network info from model. */
|
/** Update UI with latest network info from model. */
|
||||||
void updateNetworkState();
|
void updateNetworkState();
|
||||||
|
@ -147,6 +147,7 @@ void SplashScreen::slotFinish(QWidget *mainWin)
|
|||||||
if (isMinimized())
|
if (isMinimized())
|
||||||
showNormal();
|
showNormal();
|
||||||
hide();
|
hide();
|
||||||
|
deleteLater(); // No more need for this
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitMessage(SplashScreen *splash, const std::string &message)
|
static void InitMessage(SplashScreen *splash, const std::string &message)
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
|
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||||
QWidget(parent), model(0), transactionProxyModel(0),
|
QWidget(parent), model(0), transactionProxyModel(0),
|
||||||
transactionView(0), abandonAction(0)
|
transactionView(0), abandonAction(0), columnResizingFixer(0)
|
||||||
{
|
{
|
||||||
// Build filter row
|
// Build filter row
|
||||||
setContentsMargins(0,0,0,0);
|
setContentsMargins(0,0,0,0);
|
||||||
@ -147,7 +147,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
|
|||||||
QAction *editLabelAction = new QAction(tr("Edit label"), this);
|
QAction *editLabelAction = new QAction(tr("Edit label"), this);
|
||||||
QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
|
QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
|
||||||
|
|
||||||
contextMenu = new QMenu();
|
contextMenu = new QMenu(this);
|
||||||
contextMenu->addAction(copyAddressAction);
|
contextMenu->addAction(copyAddressAction);
|
||||||
contextMenu->addAction(copyLabelAction);
|
contextMenu->addAction(copyLabelAction);
|
||||||
contextMenu->addAction(copyAmountAction);
|
contextMenu->addAction(copyAmountAction);
|
||||||
@ -212,7 +212,7 @@ void TransactionView::setModel(WalletModel *_model)
|
|||||||
transactionView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
|
transactionView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
|
||||||
transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
|
transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
|
||||||
|
|
||||||
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
|
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH, this);
|
||||||
|
|
||||||
if (_model->getOptionsModel())
|
if (_model->getOptionsModel())
|
||||||
{
|
{
|
||||||
|
@ -171,22 +171,20 @@ ShutdownWindow::ShutdownWindow(QWidget *parent, Qt::WindowFlags f):
|
|||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownWindow::showShutdownWindow(BitcoinGUI *window)
|
QWidget *ShutdownWindow::showShutdownWindow(BitcoinGUI *window)
|
||||||
{
|
{
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return nullptr;
|
||||||
|
|
||||||
// Show a simple window indicating shutdown status
|
// Show a simple window indicating shutdown status
|
||||||
QWidget *shutdownWindow = new ShutdownWindow();
|
QWidget *shutdownWindow = new ShutdownWindow();
|
||||||
// We don't hold a direct pointer to the shutdown window after creation, so use
|
|
||||||
// Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually.
|
|
||||||
shutdownWindow->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
shutdownWindow->setWindowTitle(window->windowTitle());
|
shutdownWindow->setWindowTitle(window->windowTitle());
|
||||||
|
|
||||||
// Center shutdown window at where main window was
|
// Center shutdown window at where main window was
|
||||||
const QPoint global = window->mapToGlobal(window->rect().center());
|
const QPoint global = window->mapToGlobal(window->rect().center());
|
||||||
shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2);
|
shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2);
|
||||||
shutdownWindow->show();
|
shutdownWindow->show();
|
||||||
|
return shutdownWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownWindow::closeEvent(QCloseEvent *event)
|
void ShutdownWindow::closeEvent(QCloseEvent *event)
|
||||||
|
@ -43,7 +43,7 @@ class ShutdownWindow : public QWidget
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0);
|
ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0);
|
||||||
static void showShutdownWindow(BitcoinGUI *window);
|
static QWidget *showShutdownWindow(BitcoinGUI *window);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user