/*
* Qt4 bitcoin GUI.
*
- * W.J. van der Laan 20011-2012
- * The Bitcoin Developers 20011-2012
+ * W.J. van der Laan 2011-2012
+ * The Bitcoin Developers 2011-2012
*/
+
+#include "checkpoints.h"
+
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookpage.h"
#include <QStackedWidget>
#include <QDateTime>
#include <QMovie>
+#include <QFileDialog>
+#include <QDesktopServices>
+#include <QTimer>
#include <QDragEnterEvent>
#include <QUrl>
BitcoinGUI::~BitcoinGUI()
{
+ if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
+ trayIcon->hide();
#ifdef Q_WS_MAC
delete appMenuBar;
#endif
#endif
tabGroup->addAction(messageAction);
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
- connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage()));
quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this);
encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet"));
encryptWalletAction->setCheckable(true);
+ backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet"), this);
+ backupWalletAction->setToolTip(tr("Backup wallet to another location"));
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase"), this);
changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption"));
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
- connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormal()));
+ connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
+ connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
}
// Configure the menus
QMenu *file = appMenuBar->addMenu(tr("&File"));
+ file->addAction(backupWalletAction);
file->addAction(exportAction);
#ifndef FIRST_CLASS_MESSAGING
file->addAction(messageAction);
- file->addSeparator();
#endif
+ file->addSeparator();
file->addAction(quitAction);
QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
QString text;
// Represent time from last generated block in human readable text
- if(secs < 60)
+ if(secs <= 0)
+ {
+ // Fully up to date. Leave text empty.
+ }
+ else if(secs < 60)
{
text = tr("%n second(s) ago","",secs);
}
}
// Set icon state: spinning if catching up, tick otherwise
- if(secs < 30*60)
+ if(secs < 90*60 && count >= Checkpoints::GetTotalBlocksEstimate())
{
- tooltip = tr("Up to date") + QString("\n") + tooltip;
+ tooltip = tr("Up to date") + QString(".\n") + tooltip;
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
}
else
syncIconMovie->start();
}
- tooltip += QString("\n");
- tooltip += tr("Last received block was generated %1.").arg(text);
+ if(!text.isEmpty())
+ {
+ tooltip += QString("\n");
+ tooltip += tr("Last received block was generated %1.").arg(text);
+ }
labelBlocksIcon->setToolTip(tooltip);
progressBarLabel->setToolTip(tooltip);
setNumBlocks(clientModel->getNumBlocks());
}
-void BitcoinGUI::error(const QString &title, const QString &message)
+bool HACK_SHUTDOWN = false;
+
+void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
{
// Report errors from network/worker thread
- notificator->notify(Notificator::Critical, title, message);
+ if (modal)
+ {
+ QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok);
+ if (HACK_SHUTDOWN)
+ QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+ } else {
+ notificator->notify(Notificator::Critical, title, message);
+ }
}
void BitcoinGUI::changeEvent(QEvent *e)
{
+ QMainWindow::changeEvent(e);
#ifndef Q_WS_MAC // Ignored on Mac
if(e->type() == QEvent::WindowStateChange)
{
if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray())
{
QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
- bool wasMinimized = wsevt->oldState() & Qt::WindowMinimized;
- bool isMinimized = windowState() & Qt::WindowMinimized;
- if(!wasMinimized && isMinimized)
+ if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
{
- // Minimized, hide the window from taskbar
- setWindowFlags(windowFlags() | Qt::Tool);
- return;
- }
- else if(wasMinimized && !isMinimized)
- {
- // Unminimized, show the window in taskbar
- setWindowFlags(windowFlags() &~ Qt::Tool);
+ QTimer::singleShot(0, this, SLOT(hide()));
+ e->ignore();
}
}
}
#endif
- QMainWindow::changeEvent(e);
}
void BitcoinGUI::closeEvent(QCloseEvent *event)
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
{
- // Accept only URLs
+ // Accept only URIs
if(event->mimeData()->hasUrls())
event->acceptProposedAction();
}
if(event->mimeData()->hasUrls())
{
gotoSendCoinsPage();
- QList<QUrl> urls = event->mimeData()->urls();
- foreach(const QUrl &url, urls)
+ QList<QUrl> uris = event->mimeData()->urls();
+ foreach(const QUrl &uri, uris)
{
- sendCoinsPage->handleURL(&url);
+ sendCoinsPage->handleURI(uri.toString());
}
}
event->acceptProposedAction();
}
-void BitcoinGUI::handleURL(QString strURL)
+void BitcoinGUI::handleURI(QString strURI)
{
gotoSendCoinsPage();
- QUrl url = QUrl(strURL);
- sendCoinsPage->handleURL(&url);
+ sendCoinsPage->handleURI(strURI);
+
+ if(!isActiveWindow())
+ activateWindow();
+
+ showNormalIfMinimized();
}
void BitcoinGUI::setEncryptionStatus(int status)
setEncryptionStatus(walletModel->getEncryptionStatus());
}
+void BitcoinGUI::backupWallet()
+{
+ QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+ QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
+ if(!filename.isEmpty()) {
+ if(!walletModel->backupWallet(filename)) {
+ QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."));
+ }
+ }
+}
+
void BitcoinGUI::changePassphrase()
{
AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
dlg.exec();
}
}
+
+void BitcoinGUI::showNormalIfMinimized()
+{
+ if(!isVisible()) // Show, if hidden
+ show();
+ if(isMinimized()) // Unminimize, if minimized
+ showNormal();
+}