2015-04-29 17:03:08 +00:00
|
|
|
// Copyright (c) 2011-2015 The Cryptonote developers
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#include <QCloseEvent>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QInputDialog>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QSystemTrayIcon>
|
|
|
|
#include <QTimer>
|
|
|
|
|
2015-09-18 12:37:30 +00:00
|
|
|
#include <Common/Util.h>
|
2015-04-29 17:03:08 +00:00
|
|
|
|
|
|
|
#include "AboutDialog.h"
|
|
|
|
#include "AnimatedLabel.h"
|
|
|
|
#include "ChangePasswordDialog.h"
|
|
|
|
#include "CurrencyAdapter.h"
|
|
|
|
#include "ExitWidget.h"
|
|
|
|
#include "MainWindow.h"
|
|
|
|
#include "NewPasswordDialog.h"
|
|
|
|
#include "NodeAdapter.h"
|
|
|
|
#include "PasswordDialog.h"
|
|
|
|
#include "Settings.h"
|
|
|
|
#include "WalletAdapter.h"
|
|
|
|
#include "WalletEvents.h"
|
|
|
|
|
|
|
|
#include "ui_mainwindow.h"
|
|
|
|
|
|
|
|
namespace WalletGui {
|
|
|
|
|
|
|
|
MainWindow* MainWindow::m_instance = nullptr;
|
|
|
|
|
|
|
|
MainWindow& MainWindow::instance() {
|
|
|
|
if (m_instance == nullptr) {
|
|
|
|
m_instance = new MainWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *m_instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
MainWindow::MainWindow() : QMainWindow(), m_ui(new Ui::MainWindow), m_trayIcon(nullptr), m_tabActionGroup(new QActionGroup(this)),
|
|
|
|
m_isAboutToQuit(false) {
|
|
|
|
m_ui->setupUi(this);
|
|
|
|
m_connectionStateIconLabel = new QLabel(this);
|
|
|
|
m_encryptionStateIconLabel = new QLabel(this);
|
|
|
|
m_synchronizationStateIconLabel = new AnimatedLabel(this);
|
|
|
|
|
|
|
|
connectToSignals();
|
|
|
|
initUi();
|
|
|
|
|
|
|
|
walletClosed();
|
|
|
|
}
|
|
|
|
|
|
|
|
MainWindow::~MainWindow() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::connectToSignals() {
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::openWalletWithPasswordSignal, this, &MainWindow::askForWalletPassword, Qt::QueuedConnection);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::changeWalletPasswordSignal, this, &MainWindow::encryptWallet, Qt::QueuedConnection);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::walletSynchronizationProgressUpdatedSignal,
|
|
|
|
this, &MainWindow::walletSynchronizationInProgress, Qt::QueuedConnection);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::walletSynchronizationCompletedSignal, this, &MainWindow::walletSynchronized
|
|
|
|
, Qt::QueuedConnection);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::walletStateChangedSignal, this, &MainWindow::setStatusBarText);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::walletInitCompletedSignal, this, &MainWindow::walletOpened);
|
|
|
|
connect(&WalletAdapter::instance(), &WalletAdapter::walletCloseCompletedSignal, this, &MainWindow::walletClosed);
|
|
|
|
connect(&NodeAdapter::instance(), &NodeAdapter::peerCountUpdatedSignal, this, &MainWindow::peerCountUpdated, Qt::QueuedConnection);
|
|
|
|
connect(m_ui->m_exitAction, &QAction::triggered, qApp, &QApplication::quit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::initUi() {
|
|
|
|
setWindowTitle(QString("%1 Wallet %2").arg(CurrencyAdapter::instance().getCurrencyDisplayName()).arg(Settings::instance().getVersion()));
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
|
|
|
m_trayIcon = new QSystemTrayIcon(QPixmap(":images/cryptonote"), this);
|
|
|
|
connect(m_trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayActivated);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
m_ui->m_aboutCryptonoteAction->setText(QString(tr("About %1 Wallet")).arg(CurrencyAdapter::instance().getCurrencyDisplayName()));
|
|
|
|
|
|
|
|
m_ui->m_overviewFrame->hide();
|
|
|
|
m_ui->m_sendFrame->hide();
|
|
|
|
m_ui->m_receiveFrame->hide();
|
|
|
|
m_ui->m_transactionsFrame->hide();
|
|
|
|
m_ui->m_addressBookFrame->hide();
|
|
|
|
|
|
|
|
m_tabActionGroup->addAction(m_ui->m_overviewAction);
|
|
|
|
m_tabActionGroup->addAction(m_ui->m_sendAction);
|
|
|
|
m_tabActionGroup->addAction(m_ui->m_receiveAction);
|
|
|
|
m_tabActionGroup->addAction(m_ui->m_transactionsAction);
|
|
|
|
m_tabActionGroup->addAction(m_ui->m_addressBookAction);
|
|
|
|
|
|
|
|
m_ui->m_overviewAction->toggle();
|
|
|
|
encryptedFlagChanged(false);
|
|
|
|
statusBar()->addPermanentWidget(m_connectionStateIconLabel);
|
|
|
|
statusBar()->addPermanentWidget(m_encryptionStateIconLabel);
|
|
|
|
statusBar()->addPermanentWidget(m_synchronizationStateIconLabel);
|
|
|
|
qobject_cast<AnimatedLabel*>(m_synchronizationStateIconLabel)->setSprite(QPixmap(":icons/sync_sprite"), QSize(16, 16), 5, 24);
|
|
|
|
m_connectionStateIconLabel->setPixmap(QPixmap(":icons/disconnected").scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
|
|
|
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
installDockHandler();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef Q_OS_WIN
|
|
|
|
m_ui->m_minimizeToTrayAction->deleteLater();
|
|
|
|
m_ui->m_closeToTrayAction->deleteLater();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
void MainWindow::minimizeToTray(bool _on) {
|
|
|
|
if (_on) {
|
|
|
|
hide();
|
|
|
|
m_trayIcon->show();
|
|
|
|
} else {
|
|
|
|
showNormal();
|
|
|
|
activateWindow();
|
|
|
|
m_trayIcon->hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void MainWindow::scrollToTransaction(const QModelIndex& _index) {
|
|
|
|
m_ui->m_transactionsAction->setChecked(true);
|
|
|
|
m_ui->m_transactionsFrame->scrollToTransaction(_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::quit() {
|
|
|
|
if (!m_isAboutToQuit) {
|
|
|
|
ExitWidget* exitWidget = new ExitWidget(nullptr);
|
|
|
|
exitWidget->show();
|
|
|
|
m_isAboutToQuit = true;
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
void MainWindow::restoreFromDock() {
|
|
|
|
if (m_isAboutToQuit) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
showNormal();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void MainWindow::closeEvent(QCloseEvent* _event) {
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
if (m_isAboutToQuit) {
|
|
|
|
QMainWindow::closeEvent(_event);
|
|
|
|
return;
|
|
|
|
} else if (Settings::instance().isCloseToTrayEnabled()) {
|
|
|
|
minimizeToTray(true);
|
|
|
|
_event->ignore();
|
|
|
|
} else {
|
|
|
|
QApplication::quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (!m_isAboutToQuit) {
|
|
|
|
QApplication::quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
QMainWindow::closeEvent(_event);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
void MainWindow::changeEvent(QEvent* _event) {
|
|
|
|
QMainWindow::changeEvent(_event);
|
|
|
|
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
|
|
|
|
QMainWindow::changeEvent(_event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (_event->type()) {
|
|
|
|
case QEvent::WindowStateChange:
|
|
|
|
if(Settings::instance().isMinimizeToTrayEnabled()) {
|
|
|
|
minimizeToTray(isMinimized());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMainWindow::changeEvent(_event);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool MainWindow::event(QEvent* _event) {
|
|
|
|
switch (static_cast<WalletEventType>(_event->type())) {
|
|
|
|
case WalletEventType::ShowMessage:
|
|
|
|
showMessage(static_cast<ShowMessageEvent*>(_event)->messageText(), static_cast<ShowMessageEvent*>(_event)->messageType());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QMainWindow::event(_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::createWallet() {
|
|
|
|
QString filePath = QFileDialog::getSaveFileName(this, tr("New wallet file"),
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
QApplication::applicationDirPath(),
|
|
|
|
#else
|
|
|
|
QDir::homePath(),
|
|
|
|
#endif
|
|
|
|
tr("Wallets (*.wallet)")
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!filePath.isEmpty() && !filePath.endsWith(".wallet")) {
|
|
|
|
filePath.append(".wallet");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filePath.isEmpty() && !QFile::exists(filePath)) {
|
|
|
|
if (WalletAdapter::instance().isOpen()) {
|
|
|
|
WalletAdapter::instance().close();
|
|
|
|
}
|
|
|
|
|
|
|
|
WalletAdapter::instance().setWalletFile(filePath);
|
|
|
|
WalletAdapter::instance().open("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::openWallet() {
|
|
|
|
QString filePath = QFileDialog::getOpenFileName(this, tr("Open .wallet/.keys file"),
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
QApplication::applicationDirPath(),
|
|
|
|
#else
|
|
|
|
QDir::homePath(),
|
|
|
|
#endif
|
|
|
|
tr("Wallet (*.wallet *.keys)"));
|
|
|
|
|
|
|
|
if (!filePath.isEmpty()) {
|
|
|
|
if (WalletAdapter::instance().isOpen()) {
|
|
|
|
WalletAdapter::instance().close();
|
|
|
|
}
|
|
|
|
|
|
|
|
WalletAdapter::instance().setWalletFile(filePath);
|
|
|
|
WalletAdapter::instance().open("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::backupWallet() {
|
|
|
|
QString filePath = QFileDialog::getSaveFileName(this, tr("Backup wallet to..."),
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
QApplication::applicationDirPath(),
|
|
|
|
#else
|
|
|
|
QDir::homePath(),
|
|
|
|
#endif
|
|
|
|
tr("Wallets (*.wallet)")
|
|
|
|
);
|
|
|
|
if (!filePath.isEmpty() && !filePath.endsWith(".wallet")) {
|
|
|
|
filePath.append(".wallet");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filePath.isEmpty() && !QFile::exists(filePath)) {
|
|
|
|
WalletAdapter::instance().backup(filePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::encryptWallet() {
|
|
|
|
if (Settings::instance().isEncrypted()) {
|
|
|
|
bool error = false;
|
|
|
|
do {
|
|
|
|
ChangePasswordDialog dlg(this);
|
|
|
|
if (dlg.exec() == QDialog::Rejected) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString oldPassword = dlg.getOldPassword();
|
|
|
|
QString newPassword = dlg.getNewPassword();
|
|
|
|
error = !WalletAdapter::instance().changePassword(oldPassword, newPassword);
|
|
|
|
} while (error);
|
|
|
|
} else {
|
|
|
|
NewPasswordDialog dlg(this);
|
|
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
|
|
QString password = dlg.getPassword();
|
|
|
|
if (password.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
encryptedFlagChanged(WalletAdapter::instance().changePassword("", password));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::aboutQt() {
|
|
|
|
QMessageBox::aboutQt(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setStartOnLogin(bool _on) {
|
|
|
|
Settings::instance().setStartOnLoginEnabled(_on);
|
|
|
|
m_ui->m_startOnLoginAction->setChecked(Settings::instance().isStartOnLoginEnabled());
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setMinimizeToTray(bool _on) {
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
Settings::instance().setMinimizeToTrayEnabled(_on);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setCloseToTray(bool _on) {
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
Settings::instance().setCloseToTrayEnabled(_on);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::about() {
|
|
|
|
AboutDialog dlg(this);
|
|
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setStatusBarText(const QString& _text) {
|
|
|
|
statusBar()->showMessage(_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::showMessage(const QString& _text, QtMsgType _type) {
|
|
|
|
switch (_type) {
|
|
|
|
case QtCriticalMsg:
|
|
|
|
QMessageBox::critical(this, tr("Wallet error"), _text);
|
|
|
|
break;
|
|
|
|
case QtDebugMsg:
|
|
|
|
QMessageBox::information(this, tr("Wallet"), _text);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::askForWalletPassword(bool _error) {
|
|
|
|
PasswordDialog dlg(_error, this);
|
|
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
|
|
QString password = dlg.getPassword();
|
|
|
|
WalletAdapter::instance().open(password);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::encryptedFlagChanged(bool _encrypted) {
|
|
|
|
m_ui->m_encryptWalletAction->setEnabled(!_encrypted);
|
|
|
|
m_ui->m_changePasswordAction->setEnabled(_encrypted);
|
|
|
|
QString encryptionIconPath = _encrypted ? ":icons/encrypted" : ":icons/decrypted";
|
|
|
|
QPixmap encryptionIcon = QPixmap(encryptionIconPath).scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
|
|
|
m_encryptionStateIconLabel->setPixmap(encryptionIcon);
|
|
|
|
QString encryptionLabelTooltip = _encrypted ? tr("Encrypted") : tr("Not encrypted");
|
|
|
|
m_encryptionStateIconLabel->setToolTip(encryptionLabelTooltip);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::peerCountUpdated(quint64 _peerCount) {
|
|
|
|
QString connectionIconPath = _peerCount > 0 ? ":icons/connected" : ":icons/disconnected";
|
|
|
|
QPixmap connectionIcon = QPixmap(connectionIconPath).scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
|
|
|
m_connectionStateIconLabel->setPixmap(connectionIcon);
|
|
|
|
m_connectionStateIconLabel->setToolTip(QString(tr("%1 peers").arg(_peerCount)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::walletSynchronizationInProgress() {
|
|
|
|
qobject_cast<AnimatedLabel*>(m_synchronizationStateIconLabel)->startAnimation();
|
|
|
|
m_synchronizationStateIconLabel->setToolTip(tr("Synchronization in progress"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::walletSynchronized(int _error, const QString& _error_text) {
|
|
|
|
QPixmap syncIcon = QPixmap(":icons/synced").scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
|
|
|
qobject_cast<AnimatedLabel*>(m_synchronizationStateIconLabel)->stopAnimation();
|
|
|
|
m_synchronizationStateIconLabel->setPixmap(syncIcon);
|
|
|
|
QString syncLabelTooltip = _error > 0 ? tr("Not synchronized") : tr("Synchronized");
|
|
|
|
m_synchronizationStateIconLabel->setToolTip(syncLabelTooltip);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::walletOpened(bool _error, const QString& _error_text) {
|
|
|
|
if (!_error) {
|
|
|
|
m_encryptionStateIconLabel->show();
|
|
|
|
m_synchronizationStateIconLabel->show();
|
|
|
|
m_ui->m_backupWalletAction->setEnabled(true);
|
|
|
|
encryptedFlagChanged(Settings::instance().isEncrypted());
|
|
|
|
|
|
|
|
QList<QAction*> tabActions = m_tabActionGroup->actions();
|
|
|
|
Q_FOREACH(auto action, tabActions) {
|
|
|
|
action->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ui->m_overviewAction->trigger();
|
|
|
|
m_ui->m_overviewFrame->show();
|
|
|
|
} else {
|
|
|
|
walletClosed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::walletClosed() {
|
|
|
|
m_ui->m_backupWalletAction->setEnabled(false);
|
|
|
|
m_ui->m_encryptWalletAction->setEnabled(false);
|
|
|
|
m_ui->m_changePasswordAction->setEnabled(false);
|
|
|
|
m_ui->m_overviewFrame->hide();
|
|
|
|
m_ui->m_sendFrame->hide();
|
|
|
|
m_ui->m_transactionsFrame->hide();
|
|
|
|
m_ui->m_addressBookFrame->hide();
|
|
|
|
m_encryptionStateIconLabel->hide();
|
|
|
|
m_synchronizationStateIconLabel->hide();
|
|
|
|
QList<QAction*> tabActions = m_tabActionGroup->actions();
|
|
|
|
Q_FOREACH(auto action, tabActions) {
|
|
|
|
action->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason _reason) {
|
|
|
|
showNormal();
|
|
|
|
m_trayIcon->hide();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|