Improved Mac experience; QDoubleSpinBox for BitcoinAmountField
[novacoin.git] / src / qt / bitcoingui.cpp
index 7943684..beffa85 100644 (file)
 #include "guiconstants.h"
 #include "askpassphrasedialog.h"
 #include "notificator.h"
-#include "qtwin.h"
+
+#ifdef Q_WS_MAC
+#include "macdockiconhandler.h"
+#endif
 
 #include <QApplication>
 #include <QMainWindow>
@@ -58,40 +61,26 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
 {
     resize(850, 550);
     setWindowTitle(tr("Bitcoin Wallet"));
+#ifndef Q_WS_MAC
     setWindowIcon(QIcon(":icons/bitcoin"));
+#else
+    setUnifiedTitleAndToolBarOnMac(true);
+    QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
+#endif
     // Accept D&D of URIs
     setAcceptDrops(true);
 
+    // Create actions for the toolbar, menu bar and tray/dock icon
     createActions();
 
-    // Menus
-    QMenu *file = menuBar()->addMenu(tr("&File"));
-    file->addAction(sendCoinsAction);
-    file->addAction(receiveCoinsAction);
-    file->addSeparator();
-    file->addAction(quitAction);
-    
-    QMenu *settings = menuBar()->addMenu(tr("&Settings"));
-    settings->addAction(encryptWalletAction);
-    settings->addAction(changePassphraseAction);
-    settings->addSeparator();
-    settings->addAction(optionsAction);
+    // Create application menu bar
+    createMenuBar();
 
-    QMenu *help = menuBar()->addMenu(tr("&Help"));
-    help->addAction(aboutAction);
-    
-    // Toolbars
-    QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
-    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
-    toolbar->addAction(overviewAction);
-    toolbar->addAction(sendCoinsAction);
-    toolbar->addAction(receiveCoinsAction);
-    toolbar->addAction(historyAction);
-    toolbar->addAction(addressBookAction);
+    // Create the toolbars
+    createToolBars();
 
-    QToolBar *toolbar2 = addToolBar(tr("Actions toolbar"));
-    toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
-    toolbar2->addAction(exportAction);
+    // Create the tray icon (or setup the dock icon)
+    createTrayIcon();
 
     // Create tabs
     overviewPage = new OverviewPage();
@@ -150,8 +139,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
     statusBar()->addWidget(progressBar);
     statusBar()->addPermanentWidget(frameBlocks);
 
-    createTrayIcon();
-
     syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this);
 
     // Clicking on a transaction on the overview page simply sends you to transaction history page
@@ -160,19 +147,16 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
     // Doubleclicking on a transaction on the transaction history page shows details
     connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
 
-#ifdef Q_OS_WIN
-    // Windows-specific customization
-    if (QtWin::isCompositionEnabled())
-    {
-        QtWin::extendFrameIntoClientArea(this);
-        setContentsMargins(0, 0, 0, 0);
-    }
-#endif
-    setWindowComposition();
-
     gotoOverviewPage();
 }
 
+BitcoinGUI::~BitcoinGUI()
+{
+#ifdef Q_WS_MAC
+    delete appMenuBar;
+#endif
+}
+
 void BitcoinGUI::createActions()
 {
     QActionGroup *tabGroup = new QActionGroup(this);
@@ -208,12 +192,16 @@ void BitcoinGUI::createActions()
     connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
     connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
 
-    quitAction = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
+    quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
     quitAction->setToolTip(tr("Quit application"));
-    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
+    quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
+    quitAction->setMenuRole(QAction::QuitRole);
+    aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About %1").arg(qApp->applicationName()), this);
     aboutAction->setToolTip(tr("Show information about Bitcoin"));
+    aboutAction->setMenuRole(QAction::AboutQtRole);
     optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
     optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
+    optionsAction->setMenuRole(QAction::PreferencesRole);
     openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
     openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
     exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
@@ -232,6 +220,45 @@ void BitcoinGUI::createActions()
     connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
 }
 
+void BitcoinGUI::createMenuBar()
+{
+#ifdef Q_WS_MAC
+    // Create a decoupled menu bar on Mac which stays even if the window is closed
+    appMenuBar = new QMenuBar();
+#else
+    // Get the main window's menu bar on other platforms
+    appMenuBar = menuBar();
+#endif
+
+    // Configure the menus
+    QMenu *file = appMenuBar->addMenu(tr("&File"));
+    file->addAction(quitAction);
+
+    QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
+    settings->addAction(encryptWalletAction);
+    settings->addAction(changePassphraseAction);
+    settings->addSeparator();
+    settings->addAction(optionsAction);
+
+    QMenu *help = appMenuBar->addMenu(tr("&Help"));
+    help->addAction(aboutAction);
+}
+
+void BitcoinGUI::createToolBars()
+{
+    QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
+    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    toolbar->addAction(overviewAction);
+    toolbar->addAction(sendCoinsAction);
+    toolbar->addAction(receiveCoinsAction);
+    toolbar->addAction(historyAction);
+    toolbar->addAction(addressBookAction);
+
+    QToolBar *toolbar2 = addToolBar(tr("Actions toolbar"));
+    toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    toolbar2->addAction(exportAction);
+}
+
 void BitcoinGUI::setClientModel(ClientModel *clientModel)
 {
     this->clientModel = clientModel;
@@ -240,7 +267,11 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
     {
         QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
         setWindowTitle(title_testnet);
+#ifndef Q_WS_MAC
         setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+#else
+        MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
+#endif
         if(trayIcon)
         {
             trayIcon->setToolTip(title_testnet);
@@ -287,23 +318,39 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
 
 void BitcoinGUI::createTrayIcon()
 {
-    QMenu *trayIconMenu = new QMenu(this);
-    trayIconMenu->addAction(openBitcoinAction);
-    trayIconMenu->addAction(optionsAction);
-    trayIconMenu->addSeparator();
-    trayIconMenu->addAction(quitAction);
-
+    QMenu *trayIconMenu;
+#ifndef Q_WS_MAC
     trayIcon = new QSystemTrayIcon(this);
+    trayIconMenu = new QMenu(this);
     trayIcon->setContextMenu(trayIconMenu);
     trayIcon->setToolTip("Bitcoin client");
     trayIcon->setIcon(QIcon(":/icons/toolbar"));
     connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
             this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
     trayIcon->show();
+#else
+    // Note: On Mac, the dock icon is used to provide the tray's functionality.
+    MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
+    connect(dockIconHandler, SIGNAL(dockIconClicked()), openBitcoinAction, SLOT(trigger()));
+    trayIconMenu = dockIconHandler->dockMenu();
+#endif
+
+    // Configuration of the tray icon (or dock icon) icon menu
+    trayIconMenu->addAction(openBitcoinAction);
+    trayIconMenu->addSeparator();
+    trayIconMenu->addAction(receiveCoinsAction);
+    trayIconMenu->addAction(sendCoinsAction);
+    trayIconMenu->addSeparator();
+    trayIconMenu->addAction(optionsAction);
+#ifndef Q_WS_MAC // This is built-in on Mac
+    trayIconMenu->addSeparator();
+    trayIconMenu->addAction(quitAction);
+#endif
 
     notificator = new Notificator(tr("bitcoin-qt"), trayIcon);
 }
 
+#ifndef Q_WS_MAC
 void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
 {
     if(reason == QSystemTrayIcon::Trigger)
@@ -313,6 +360,7 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
     }
 
 }
+#endif
 
 void BitcoinGUI::optionsClicked()
 {
@@ -346,7 +394,7 @@ void BitcoinGUI::setNumConnections(int count)
 void BitcoinGUI::setNumBlocks(int count)
 {
     int initTotal = clientModel->getNumBlocksAtStartup();
-    int total = clientModel->getTotalBlocksEstimate();
+    int total = clientModel->getNumBlocksOfPeers();
     QString tooltip;
 
     if(count < total)
@@ -416,9 +464,10 @@ void BitcoinGUI::error(const QString &title, const QString &message)
 
 void BitcoinGUI::changeEvent(QEvent *e)
 {
+#ifndef Q_WS_MAC // Ignored on Mac
     if (e->type() == QEvent::WindowStateChange)
     {
-        if(clientModel->getOptionsModel()->getMinimizeToTray())
+        if (clientModel->getOptionsModel()->getMinimizeToTray())
         {
             if (isMinimized())
             {
@@ -432,53 +481,20 @@ void BitcoinGUI::changeEvent(QEvent *e)
             }
         }
     }
-    setWindowComposition();
+#endif
     QMainWindow::changeEvent(e);
 }
 
 void BitcoinGUI::closeEvent(QCloseEvent *event)
 {
+#ifndef Q_WS_MAC // Ignored on Mac
     if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
        !clientModel->getOptionsModel()->getMinimizeOnClose())
     {
         qApp->quit();
     }
-    QMainWindow::closeEvent(event);
-}
-
-void BitcoinGUI::setWindowComposition()
-{
-#ifdef Q_OS_WIN
-    // Make the background transparent on Windows Vista or 7, except when maximized
-    // Otherwise text becomes hard to read
-    if (QtWin::isCompositionEnabled())
-    {
-        QPalette pal = palette();
-        QColor bg = pal.window().color();
-        if(isMaximized())
-        {
-            setAttribute(Qt::WA_TranslucentBackground, false);
-            setAttribute(Qt::WA_StyledBackground, true);
-            QBrush wb = pal.window();
-            bg = wb.color();
-            bg.setAlpha(255);
-            pal.setColor(QPalette::Window, bg);
-            setPalette(pal);
-
-        }
-        else
-        {
-            setAttribute(Qt::WA_TranslucentBackground);
-            setAttribute(Qt::WA_StyledBackground, false);
-            bg.setAlpha(0);
-            pal.setColor(QPalette::Window, bg);
-            setPalette(pal);
-            setAttribute(Qt::WA_NoSystemBackground, false);
-            ensurePolished();
-            setAttribute(Qt::WA_StyledBackground, false);
-        }
-    }
 #endif
+    QMainWindow::closeEvent(event);
 }
 
 void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
@@ -529,6 +545,7 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int
 
 void BitcoinGUI::gotoOverviewPage()
 {
+    show();
     overviewAction->setChecked(true);
     centralWidget->setCurrentWidget(overviewPage);
 
@@ -538,6 +555,7 @@ void BitcoinGUI::gotoOverviewPage()
 
 void BitcoinGUI::gotoHistoryPage()
 {
+    show();
     historyAction->setChecked(true);
     centralWidget->setCurrentWidget(transactionsPage);
 
@@ -548,6 +566,7 @@ void BitcoinGUI::gotoHistoryPage()
 
 void BitcoinGUI::gotoAddressBookPage()
 {
+    show();
     addressBookAction->setChecked(true);
     centralWidget->setCurrentWidget(addressBookPage);
 
@@ -558,6 +577,7 @@ void BitcoinGUI::gotoAddressBookPage()
 
 void BitcoinGUI::gotoReceiveCoinsPage()
 {
+    show();
     receiveCoinsAction->setChecked(true);
     centralWidget->setCurrentWidget(receiveCoinsPage);
 
@@ -568,12 +588,8 @@ void BitcoinGUI::gotoReceiveCoinsPage()
 
 void BitcoinGUI::gotoSendCoinsPage()
 {
+    show();
     sendCoinsAction->setChecked(true);
-    if(centralWidget->currentWidget() != sendCoinsPage)
-    {
-        // Clear the current contents if we arrived from another tab
-        sendCoinsPage->clear();
-    }
     centralWidget->setCurrentWidget(sendCoinsPage);
 
     exportAction->setEnabled(false);