// 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 #include #include #include #include #include #include #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(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(_event->type())) { case WalletEventType::ShowMessage: showMessage(static_cast(_event)->messageText(), static_cast(_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(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(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 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 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 }