Browse Source

Merge pull request #583 from laanwj/qt3

More Qt GUI updates
- Make USE_SSL qmake build flag actually work
- Improve mac experience, general UI improvements
- Add keyboard shortcut to switch between tabs
0.8
Wladimir J. van der Laan 13 years ago
parent
commit
b68a8a6b34
  1. 18
      bitcoin-qt.pro
  2. 14
      doc/readme-qt.rst
  3. 7
      src/qt/addressbookpage.cpp
  4. 8
      src/qt/bitcoin.cpp
  5. 91
      src/qt/bitcoinamountfield.cpp
  6. 9
      src/qt/bitcoinamountfield.h
  7. 145
      src/qt/bitcoingui.cpp
  8. 7
      src/qt/bitcoingui.h
  9. 3
      src/qt/forms/sendcoinsdialog.ui
  10. 17
      src/qt/forms/sendcoinsentry.ui
  11. 2
      src/qt/locale/bitcoin_de.ts
  12. 2
      src/qt/locale/bitcoin_nl.ts
  13. 2
      src/qt/locale/bitcoin_ru.ts
  14. 37
      src/qt/macdockiconhandler.h
  15. 99
      src/qt/macdockiconhandler.mm
  16. 73
      src/qt/notificator.cpp
  17. 4
      src/qt/notificator.h
  18. 12
      src/qt/optionsdialog.cpp
  19. 1
      src/qt/overviewpage.cpp
  20. 6
      src/qt/sendcoinsdialog.cpp
  21. 4
      src/qt/sendcoinsentry.cpp
  22. 31
      src/qt/transactionview.cpp

18
bitcoin-qt.pro

@ -17,10 +17,17 @@ OBJECTS_DIR = build
MOC_DIR = build MOC_DIR = build
UI_DIR = build UI_DIR = build
# use: qmake "USE_UPNP=0" (disable by default) or "USE_UPNP=1" (enable by default) # use: qmake "USE_UPNP=1" ( enabled by default; default)
# miniupnpc (http://miniupnp.free.fr/files/) must be installed # or: qmake "USE_UPNP=0" (disabled by default)
count(USE_UPNP, 1) { # or: qmake "USE_UPNP=-" (not supported)
# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support
contains(USE_UPNP, -) {
message(Building without UPNP support)
} else {
message(Building with UPNP support) message(Building with UPNP support)
count(USE_UPNP, 0) {
USE_UPNP=1
}
DEFINES += USE_UPNP=$$USE_UPNP DEFINES += USE_UPNP=$$USE_UPNP
LIBS += -lminiupnpc LIBS += -lminiupnpc
} }
@ -33,7 +40,7 @@ contains(USE_DBUS, 1) {
} }
# use: qmake "USE_SSL=1" # use: qmake "USE_SSL=1"
contains(USE_DBUS, 1) { contains(USE_SSL, 1) {
message(Building with SSL support for RPC) message(Building with SSL support for RPC)
DEFINES += USE_SSL DEFINES += USE_SSL
} }
@ -221,6 +228,9 @@ windows:LIBS += -lws2_32 -lgdi32
windows:DEFINES += WIN32 windows:DEFINES += WIN32
windows:RC_FILE = src/qt/res/bitcoin-qt.rc windows:RC_FILE = src/qt/res/bitcoin-qt.rc
macx:HEADERS += src/qt/macdockiconhandler.h
macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3 macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3
macx:ICON = src/qt/res/icons/bitcoin.icns macx:ICON = src/qt/res/icons/bitcoin.icns
macx:TARGET = "Bitcoin-Qt" macx:TARGET = "Bitcoin-Qt"

14
doc/readme-qt.rst

@ -119,13 +119,13 @@ http://miniupnp.tuxfamily.org/files/. UPnP support is not compiled in by defaul
Set USE_UPNP to a different value to control this: Set USE_UPNP to a different value to control this:
+------------+--------------------------------------------------------------+ +------------+--------------------------------------------------------------------------+
| USE_UPNP= | (the default) no UPnP support, miniupnpc not required; | | USE_UPNP=- | no UPnP support, miniupnpc not required; |
+------------+--------------------------------------------------------------+ +------------+--------------------------------------------------------------------------+
| USE_UPNP=0 | UPnP support turned off by default at runtime; | | USE_UPNP=0 | (the default) built with UPnP, support turned off by default at runtime; |
+------------+--------------------------------------------------------------+ +------------+--------------------------------------------------------------------------+
| USE_UPNP=1 | UPnP support turned on by default at runtime. | | USE_UPNP=1 | build with UPnP support turned on by default at runtime. |
+------------+--------------------------------------------------------------+ +------------+--------------------------------------------------------------------------+
Mac OS X users: miniupnpc is currently outdated on MacPorts. An updated Portfile is provided in contrib/miniupnpc within this project. Mac OS X users: miniupnpc is currently outdated on MacPorts. An updated Portfile is provided in contrib/miniupnpc within this project.
You can execute the following commands in a terminal to install it: You can execute the following commands in a terminal to install it:

7
src/qt/addressbookpage.cpp

@ -18,6 +18,13 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
tab(tab) tab(tab)
{ {
ui->setupUi(this); ui->setupUi(this);
#ifdef Q_WS_MAC // Icons on push buttons are very uncommon on Mac
ui->newAddressButton->setIcon(QIcon());
ui->copyToClipboard->setIcon(QIcon());
ui->deleteButton->setIcon(QIcon());
#endif
switch(mode) switch(mode)
{ {
case ForSending: case ForSending:

8
src/qt/bitcoin.cpp

@ -16,6 +16,7 @@
#include <QLocale> #include <QLocale>
#include <QTranslator> #include <QTranslator>
#include <QSplashScreen> #include <QSplashScreen>
#include <QLibraryInfo>
// Need a global reference for the notifications to find the GUI // Need a global reference for the notifications to find the GUI
BitcoinGUI *guiref; BitcoinGUI *guiref;
@ -119,10 +120,17 @@ int main(int argc, char *argv[])
// Load language file for system locale // Load language file for system locale
QString locale = QLocale::system().name(); QString locale = QLocale::system().name();
QTranslator qtTranslator;
qtTranslator.load(QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + locale);
if (!qtTranslator.isEmpty())
app.installTranslator(&qtTranslator);
QTranslator translator; QTranslator translator;
translator.load(":/translations/"+locale); translator.load(":/translations/"+locale);
if (!translator.isEmpty())
app.installTranslator(&translator); app.installTranslator(&translator);
app.setApplicationName(QApplication::translate("main", "Bitcoin Qt"));
QSplashScreen splash(QPixmap(":/images/splash"), 0); QSplashScreen splash(QPixmap(":/images/splash"), 0);
splash.show(); splash.show();
splash.setAutoFillBackground(true); splash.setAutoFillBackground(true);

91
src/qt/bitcoinamountfield.cpp

@ -1,33 +1,30 @@
#include "bitcoinamountfield.h" #include "bitcoinamountfield.h"
#include "qvalidatedlineedit.h"
#include "qvaluecombobox.h" #include "qvaluecombobox.h"
#include "bitcoinunits.h" #include "bitcoinunits.h"
#include "guiconstants.h"
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QRegExpValidator> #include <QRegExpValidator>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QDoubleSpinBox>
#include <QComboBox> #include <QComboBox>
#include <QApplication>
#include <qmath.h>
BitcoinAmountField::BitcoinAmountField(QWidget *parent): BitcoinAmountField::BitcoinAmountField(QWidget *parent):
QWidget(parent), amount(0), decimals(0), currentUnit(-1) QWidget(parent), amount(0), currentUnit(-1)
{ {
amount = new QValidatedLineEdit(this); amount = new QDoubleSpinBox(this);
amount->setValidator(new QRegExpValidator(QRegExp("[0-9]*"), this)); amount->setLocale(QLocale::c());
amount->setAlignment(Qt::AlignRight|Qt::AlignVCenter); amount->setDecimals(8);
amount->installEventFilter(this); amount->installEventFilter(this);
amount->setMaximumWidth(75); amount->setMaximumWidth(170);
decimals = new QValidatedLineEdit(this);
decimals->setValidator(new QRegExpValidator(QRegExp("[0-9]+"), this));
decimals->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
decimals->setMaximumWidth(75);
QHBoxLayout *layout = new QHBoxLayout(this); QHBoxLayout *layout = new QHBoxLayout(this);
layout->setSpacing(0);
layout->addWidget(amount); layout->addWidget(amount);
layout->addWidget(new QLabel(QString("<b>.</b>")));
layout->addWidget(decimals);
unit = new QValueComboBox(this); unit = new QValueComboBox(this);
unit->setModel(new BitcoinUnits(this)); unit->setModel(new BitcoinUnits(this));
layout->addWidget(unit); layout->addWidget(unit);
@ -40,8 +37,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent):
setFocusProxy(amount); setFocusProxy(amount);
// If one if the widgets changes, the combined content changes as well // If one if the widgets changes, the combined content changes as well
connect(amount, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged())); connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
connect(decimals, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged()));
connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int))); connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
// Set default based on configuration // Set default based on configuration
@ -50,79 +46,72 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent):
void BitcoinAmountField::setText(const QString &text) void BitcoinAmountField::setText(const QString &text)
{ {
const QStringList parts = text.split(QString(".")); if (text.isEmpty())
if(parts.size() == 2) amount->clear();
{
amount->setText(parts[0]);
decimals->setText(parts[1]);
}
else else
{ amount->setValue(text.toDouble());
amount->setText(QString());
decimals->setText(QString());
}
} }
void BitcoinAmountField::clear() void BitcoinAmountField::clear()
{ {
amount->clear(); amount->clear();
decimals->clear();
unit->setCurrentIndex(0); unit->setCurrentIndex(0);
} }
bool BitcoinAmountField::validate() bool BitcoinAmountField::validate()
{ {
bool valid = true; bool valid = true;
if(decimals->text().isEmpty()) if (amount->value() == 0.0)
{
decimals->setValid(false);
valid = false; valid = false;
} if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
if(!BitcoinUnits::parse(currentUnit, text(), 0))
{
setValid(false);
valid = false; valid = false;
}
setValid(valid);
return valid; return valid;
} }
void BitcoinAmountField::setValid(bool valid) void BitcoinAmountField::setValid(bool valid)
{ {
amount->setValid(valid); if (valid)
decimals->setValid(valid); amount->setStyleSheet("");
else
amount->setStyleSheet(STYLE_INVALID);
} }
QString BitcoinAmountField::text() const QString BitcoinAmountField::text() const
{ {
if(decimals->text().isEmpty() && amount->text().isEmpty()) if (amount->text().isEmpty())
{
return QString(); return QString();
} else
return amount->text() + QString(".") + decimals->text(); return amount->text();
} }
// Intercept '.' and ',' keys, if pressed focus a specified widget
bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event) bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{ {
Q_UNUSED(object); if (event->type() == QEvent::FocusIn)
if(event->type() == QEvent::KeyPress) {
// Clear invalid flag on focus
setValid(true);
}
else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
{ {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Period || keyEvent->key() == Qt::Key_Comma) if (keyEvent->key() == Qt::Key_Comma)
{ {
decimals->setFocus(); // Translate a comma into a period
decimals->selectAll(); QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
qApp->sendEvent(object, &periodKeyEvent);
return true;
} }
} }
return false; return QWidget::eventFilter(object, event);
} }
QWidget *BitcoinAmountField::setupTabChain(QWidget *prev) QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
{ {
QWidget::setTabOrder(prev, amount); QWidget::setTabOrder(prev, amount);
QWidget::setTabOrder(amount, decimals); return amount;
return decimals;
} }
qint64 BitcoinAmountField::value(bool *valid_out) const qint64 BitcoinAmountField::value(bool *valid_out) const
@ -156,8 +145,8 @@ void BitcoinAmountField::unitChanged(int idx)
currentUnit = newUnit; currentUnit = newUnit;
// Set max length after retrieving the value, to prevent truncation // Set max length after retrieving the value, to prevent truncation
amount->setMaxLength(BitcoinUnits::amountDigits(currentUnit)); amount->setDecimals(BitcoinUnits::decimals(currentUnit));
decimals->setMaxLength(BitcoinUnits::decimals(currentUnit)); amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));
if(valid) if(valid)
{ {

9
src/qt/bitcoinamountfield.h

@ -4,7 +4,7 @@
#include <QWidget> #include <QWidget>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QValidatedLineEdit; class QDoubleSpinBox;
class QValueComboBox; class QValueComboBox;
QT_END_NAMESPACE QT_END_NAMESPACE
@ -13,7 +13,7 @@ QT_END_NAMESPACE
class BitcoinAmountField: public QWidget class BitcoinAmountField: public QWidget
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true); Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true)
public: public:
explicit BitcoinAmountField(QWidget *parent = 0); explicit BitcoinAmountField(QWidget *parent = 0);
@ -38,12 +38,11 @@ signals:
void textChanged(); void textChanged();
protected: protected:
// Intercept '.' and ',' keys, if pressed focus a specified widget // Intercept focus-in event and ',' keypresses
bool eventFilter(QObject *object, QEvent *event); bool eventFilter(QObject *object, QEvent *event);
private: private:
QValidatedLineEdit *amount; QDoubleSpinBox *amount;
QValidatedLineEdit *decimals;
QValueComboBox *unit; QValueComboBox *unit;
int currentUnit; int currentUnit;

145
src/qt/bitcoingui.cpp

@ -22,6 +22,10 @@
#include "askpassphrasedialog.h" #include "askpassphrasedialog.h"
#include "notificator.h" #include "notificator.h"
#ifdef Q_WS_MAC
#include "macdockiconhandler.h"
#endif
#include <QApplication> #include <QApplication>
#include <QMainWindow> #include <QMainWindow>
#include <QMenuBar> #include <QMenuBar>
@ -57,40 +61,26 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
{ {
resize(850, 550); resize(850, 550);
setWindowTitle(tr("Bitcoin Wallet")); setWindowTitle(tr("Bitcoin Wallet"));
#ifndef Q_WS_MAC
setWindowIcon(QIcon(":icons/bitcoin")); setWindowIcon(QIcon(":icons/bitcoin"));
#else
setUnifiedTitleAndToolBarOnMac(true);
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
#endif
// Accept D&D of URIs // Accept D&D of URIs
setAcceptDrops(true); setAcceptDrops(true);
// Create actions for the toolbar, menu bar and tray/dock icon
createActions(); createActions();
// Menus // Create application menu bar
QMenu *file = menuBar()->addMenu(tr("&File")); createMenuBar();
file->addAction(sendCoinsAction);
file->addAction(receiveCoinsAction);
file->addSeparator();
file->addAction(quitAction);
QMenu *settings = menuBar()->addMenu(tr("&Settings")); // Create the toolbars
settings->addAction(encryptWalletAction); createToolBars();
settings->addAction(changePassphraseAction);
settings->addSeparator();
settings->addAction(optionsAction);
QMenu *help = menuBar()->addMenu(tr("&Help"));
help->addAction(aboutAction);
// Toolbars // Create the tray icon (or setup the dock icon)
QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); createTrayIcon();
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);
// Create tabs // Create tabs
overviewPage = new OverviewPage(); overviewPage = new OverviewPage();
@ -149,8 +139,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
statusBar()->addWidget(progressBar); statusBar()->addWidget(progressBar);
statusBar()->addPermanentWidget(frameBlocks); statusBar()->addPermanentWidget(frameBlocks);
createTrayIcon();
syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this); syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this);
// Clicking on a transaction on the overview page simply sends you to transaction history page // Clicking on a transaction on the overview page simply sends you to transaction history page
@ -162,6 +150,13 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
gotoOverviewPage(); gotoOverviewPage();
} }
BitcoinGUI::~BitcoinGUI()
{
#ifdef Q_WS_MAC
delete appMenuBar;
#endif
}
void BitcoinGUI::createActions() void BitcoinGUI::createActions()
{ {
QActionGroup *tabGroup = new QActionGroup(this); QActionGroup *tabGroup = new QActionGroup(this);
@ -169,26 +164,31 @@ void BitcoinGUI::createActions()
overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this); overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
overviewAction->setToolTip(tr("Show general overview of wallet")); overviewAction->setToolTip(tr("Show general overview of wallet"));
overviewAction->setCheckable(true); overviewAction->setCheckable(true);
overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
tabGroup->addAction(overviewAction); tabGroup->addAction(overviewAction);
historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
historyAction->setToolTip(tr("Browse transaction history")); historyAction->setToolTip(tr("Browse transaction history"));
historyAction->setCheckable(true); historyAction->setCheckable(true);
historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
tabGroup->addAction(historyAction); tabGroup->addAction(historyAction);
addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this); addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels")); addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels"));
addressBookAction->setCheckable(true); addressBookAction->setCheckable(true);
addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
tabGroup->addAction(addressBookAction); tabGroup->addAction(addressBookAction);
receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this); receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments")); receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments"));
receiveCoinsAction->setCheckable(true); receiveCoinsAction->setCheckable(true);
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
tabGroup->addAction(receiveCoinsAction); tabGroup->addAction(receiveCoinsAction);
sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this); sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address")); sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address"));
sendCoinsAction->setCheckable(true); sendCoinsAction->setCheckable(true);
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
tabGroup->addAction(sendCoinsAction); tabGroup->addAction(sendCoinsAction);
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
@ -197,12 +197,16 @@ void BitcoinGUI::createActions()
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); 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")); 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->setToolTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutQtRole);
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setToolTip(tr("Modify configuration options for bitcoin")); optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole);
openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this); openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
openBitcoinAction->setToolTip(tr("Show the Bitcoin window")); openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this); exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
@ -221,6 +225,45 @@ void BitcoinGUI::createActions()
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); 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) void BitcoinGUI::setClientModel(ClientModel *clientModel)
{ {
this->clientModel = clientModel; this->clientModel = clientModel;
@ -229,7 +272,11 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
{ {
QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]"); QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
setWindowTitle(title_testnet); setWindowTitle(title_testnet);
#ifndef Q_WS_MAC
setWindowIcon(QIcon(":icons/bitcoin_testnet")); setWindowIcon(QIcon(":icons/bitcoin_testnet"));
#else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
#endif
if(trayIcon) if(trayIcon)
{ {
trayIcon->setToolTip(title_testnet); trayIcon->setToolTip(title_testnet);
@ -276,23 +323,39 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
void BitcoinGUI::createTrayIcon() void BitcoinGUI::createTrayIcon()
{ {
QMenu *trayIconMenu = new QMenu(this); QMenu *trayIconMenu;
trayIconMenu->addAction(openBitcoinAction); #ifndef Q_WS_MAC
trayIconMenu->addAction(optionsAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
trayIcon = new QSystemTrayIcon(this); trayIcon = new QSystemTrayIcon(this);
trayIconMenu = new QMenu(this);
trayIcon->setContextMenu(trayIconMenu); trayIcon->setContextMenu(trayIconMenu);
trayIcon->setToolTip("Bitcoin client"); trayIcon->setToolTip("Bitcoin client");
trayIcon->setIcon(QIcon(":/icons/toolbar")); trayIcon->setIcon(QIcon(":/icons/toolbar"));
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
trayIcon->show(); 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); notificator = new Notificator(tr("bitcoin-qt"), trayIcon);
} }
#ifndef Q_WS_MAC
void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{ {
if(reason == QSystemTrayIcon::Trigger) if(reason == QSystemTrayIcon::Trigger)
@ -302,6 +365,7 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
} }
} }
#endif
void BitcoinGUI::optionsClicked() void BitcoinGUI::optionsClicked()
{ {
@ -405,6 +469,7 @@ void BitcoinGUI::error(const QString &title, const QString &message)
void BitcoinGUI::changeEvent(QEvent *e) void BitcoinGUI::changeEvent(QEvent *e)
{ {
#ifndef Q_WS_MAC // Ignored on Mac
if (e->type() == QEvent::WindowStateChange) if (e->type() == QEvent::WindowStateChange)
{ {
if (clientModel->getOptionsModel()->getMinimizeToTray()) if (clientModel->getOptionsModel()->getMinimizeToTray())
@ -421,16 +486,19 @@ void BitcoinGUI::changeEvent(QEvent *e)
} }
} }
} }
#endif
QMainWindow::changeEvent(e); QMainWindow::changeEvent(e);
} }
void BitcoinGUI::closeEvent(QCloseEvent *event) void BitcoinGUI::closeEvent(QCloseEvent *event)
{ {
#ifndef Q_WS_MAC // Ignored on Mac
if(!clientModel->getOptionsModel()->getMinimizeToTray() && if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
!clientModel->getOptionsModel()->getMinimizeOnClose()) !clientModel->getOptionsModel()->getMinimizeOnClose())
{ {
qApp->quit(); qApp->quit();
} }
#endif
QMainWindow::closeEvent(event); QMainWindow::closeEvent(event);
} }
@ -482,6 +550,7 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int
void BitcoinGUI::gotoOverviewPage() void BitcoinGUI::gotoOverviewPage()
{ {
show();
overviewAction->setChecked(true); overviewAction->setChecked(true);
centralWidget->setCurrentWidget(overviewPage); centralWidget->setCurrentWidget(overviewPage);
@ -491,6 +560,7 @@ void BitcoinGUI::gotoOverviewPage()
void BitcoinGUI::gotoHistoryPage() void BitcoinGUI::gotoHistoryPage()
{ {
show();
historyAction->setChecked(true); historyAction->setChecked(true);
centralWidget->setCurrentWidget(transactionsPage); centralWidget->setCurrentWidget(transactionsPage);
@ -501,6 +571,7 @@ void BitcoinGUI::gotoHistoryPage()
void BitcoinGUI::gotoAddressBookPage() void BitcoinGUI::gotoAddressBookPage()
{ {
show();
addressBookAction->setChecked(true); addressBookAction->setChecked(true);
centralWidget->setCurrentWidget(addressBookPage); centralWidget->setCurrentWidget(addressBookPage);
@ -511,6 +582,7 @@ void BitcoinGUI::gotoAddressBookPage()
void BitcoinGUI::gotoReceiveCoinsPage() void BitcoinGUI::gotoReceiveCoinsPage()
{ {
show();
receiveCoinsAction->setChecked(true); receiveCoinsAction->setChecked(true);
centralWidget->setCurrentWidget(receiveCoinsPage); centralWidget->setCurrentWidget(receiveCoinsPage);
@ -521,6 +593,7 @@ void BitcoinGUI::gotoReceiveCoinsPage()
void BitcoinGUI::gotoSendCoinsPage() void BitcoinGUI::gotoSendCoinsPage()
{ {
show();
sendCoinsAction->setChecked(true); sendCoinsAction->setChecked(true);
centralWidget->setCurrentWidget(sendCoinsPage); centralWidget->setCurrentWidget(sendCoinsPage);

7
src/qt/bitcoingui.h

@ -29,6 +29,8 @@ class BitcoinGUI : public QMainWindow
Q_OBJECT Q_OBJECT
public: public:
explicit BitcoinGUI(QWidget *parent = 0); explicit BitcoinGUI(QWidget *parent = 0);
~BitcoinGUI();
void setClientModel(ClientModel *clientModel); void setClientModel(ClientModel *clientModel);
void setWalletModel(WalletModel *walletModel); void setWalletModel(WalletModel *walletModel);
@ -64,6 +66,7 @@ private:
QLabel *progressBarLabel; QLabel *progressBarLabel;
QProgressBar *progressBar; QProgressBar *progressBar;
QMenuBar *appMenuBar;
QAction *overviewAction; QAction *overviewAction;
QAction *historyAction; QAction *historyAction;
QAction *quitAction; QAction *quitAction;
@ -84,6 +87,8 @@ private:
QMovie *syncIconMovie; QMovie *syncIconMovie;
void createActions(); void createActions();
void createMenuBar();
void createToolBars();
QWidget *createTabs(); QWidget *createTabs();
void createTrayIcon(); void createTrayIcon();
@ -110,7 +115,9 @@ private slots:
// Misc actions // Misc actions
void optionsClicked(); void optionsClicked();
void aboutClicked(); void aboutClicked();
#ifndef Q_WS_MAC
void trayIconActivated(QSystemTrayIcon::ActivationReason reason); void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
#endif
void incomingTransaction(const QModelIndex & parent, int start, int end); void incomingTransaction(const QModelIndex & parent, int start, int end);
void encryptWallet(bool status); void encryptWallet(bool status);
void changePassphrase(); void changePassphrase();

3
src/qt/forms/sendcoinsdialog.ui

@ -58,9 +58,6 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<item> <item>
<widget class="QPushButton" name="addButton"> <widget class="QPushButton" name="addButton">
<property name="toolTip"> <property name="toolTip">

17
src/qt/forms/sendcoinsentry.ui

@ -83,7 +83,7 @@
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="payToLayout">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
@ -98,7 +98,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="addressBookButton"> <widget class="QToolButton" name="addressBookButton">
<property name="toolTip"> <property name="toolTip">
<string>Choose adress from address book</string> <string>Choose adress from address book</string>
</property> </property>
@ -112,16 +112,10 @@
<property name="shortcut"> <property name="shortcut">
<string>Alt+A</string> <string>Alt+A</string>
</property> </property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pasteButton"> <widget class="QToolButton" name="pasteButton">
<property name="toolTip"> <property name="toolTip">
<string>Paste address from clipboard</string> <string>Paste address from clipboard</string>
</property> </property>
@ -135,13 +129,10 @@
<property name="shortcut"> <property name="shortcut">
<string>Alt+P</string> <string>Alt+P</string>
</property> </property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="deleteButton"> <widget class="QToolButton" name="deleteButton">
<property name="toolTip"> <property name="toolTip">
<string>Remove this recipient</string> <string>Remove this recipient</string>
</property> </property>

2
src/qt/locale/bitcoin_de.ts

@ -351,7 +351,7 @@ Are you sure you wish to encrypt your wallet?</source>
</message> </message>
<message> <message>
<location filename="../bitcoingui.cpp" line="200"/> <location filename="../bitcoingui.cpp" line="200"/>
<source>&amp;Exit</source> <source>E&amp;xit</source>
<translation>Beenden</translation> <translation>Beenden</translation>
</message> </message>
<message> <message>

2
src/qt/locale/bitcoin_nl.ts

@ -372,7 +372,7 @@ Are you sure you wish to encrypt your wallet?</source>
</message> </message>
<message> <message>
<location filename="../bitcoingui.cpp" line="200"/> <location filename="../bitcoingui.cpp" line="200"/>
<source>&amp;Exit</source> <source>E&amp;xit</source>
<translation>A&amp;fsluiten</translation> <translation>A&amp;fsluiten</translation>
</message> </message>
<message> <message>

2
src/qt/locale/bitcoin_ru.ts

@ -343,7 +343,7 @@ Are you sure you wish to encrypt your wallet?</source>
</message> </message>
<message> <message>
<location filename="../bitcoingui.cpp" line="200"/> <location filename="../bitcoingui.cpp" line="200"/>
<source>&amp;Exit</source> <source>E&amp;xit</source>
<translation>Вы&amp;ход</translation> <translation>Вы&amp;ход</translation>
</message> </message>
<message> <message>

37
src/qt/macdockiconhandler.h

@ -0,0 +1,37 @@
#ifndef MACDOCKICONHANDLER_H
#define MACDOCKICONHANDLER_H
#include <QtCore/QObject>
class QMenu;
class QIcon;
class QWidget;
class objc_object;
class MacDockIconHandler : public QObject
{
Q_OBJECT
public:
~MacDockIconHandler();
QMenu *dockMenu();
void setIcon(const QIcon &icon);
static MacDockIconHandler *instance();
void handleDockIconClickEvent();
signals:
void dockIconClicked();
public slots:
private:
MacDockIconHandler();
objc_object *m_dockIconClickEventHandler;
QWidget *m_dummyWidget;
QMenu *m_dockMenu;
};
#endif // MACDOCKICONCLICKHANDLER_H

99
src/qt/macdockiconhandler.mm

@ -0,0 +1,99 @@
#include "macdockiconhandler.h"
#include <QtGui/QMenu>
#include <QtGui/QWidget>
extern void qt_mac_set_dock_menu(QMenu*);
#undef slots
#include <Cocoa/Cocoa.h>
@interface DockIconClickEventHandler : NSObject
{
MacDockIconHandler* dockIconHandler;
}
@end
@implementation DockIconClickEventHandler
- (id)initWithDockIconHandler:(MacDockIconHandler *)aDockIconHandler
{
self = [super init];
if (self) {
dockIconHandler = aDockIconHandler;
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:@selector(handleDockClickEvent:withReplyEvent:)
forEventClass:kCoreEventClass
andEventID:kAEReopenApplication];
}
return self;
}
- (void)handleDockClickEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
Q_UNUSED(event)
Q_UNUSED(replyEvent)
if (dockIconHandler)
dockIconHandler->handleDockIconClickEvent();
}
@end
MacDockIconHandler::MacDockIconHandler() : QObject()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
this->m_dockIconClickEventHandler = [[DockIconClickEventHandler alloc] initWithDockIconHandler:this];
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
qt_mac_set_dock_menu(this->m_dockMenu);
[pool release];
}
MacDockIconHandler::~MacDockIconHandler()
{
[this->m_dockIconClickEventHandler release];
delete this->m_dummyWidget;
}
QMenu *MacDockIconHandler::dockMenu()
{
return this->m_dockMenu;
}
void MacDockIconHandler::setIcon(const QIcon &icon)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSImage *image;
if (icon.isNull())
image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
else {
QSize size = icon.actualSize(QSize(128, 128));
QPixmap pixmap = icon.pixmap(size);
CGImageRef cgImage = pixmap.toMacCGImageRef();
image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
CFRelease(cgImage);
}
[NSApp setApplicationIconImage:image];
[image release];
[pool release];
}
MacDockIconHandler *MacDockIconHandler::instance()
{
static MacDockIconHandler *s_instance = NULL;
if (!s_instance)
s_instance = new MacDockIconHandler();
return s_instance;
}
void MacDockIconHandler::handleDockIconClickEvent()
{
emit this->dockIconClicked();
}

73
src/qt/notificator.cpp

@ -8,12 +8,19 @@
#include <QByteArray> #include <QByteArray>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QMessageBox> #include <QMessageBox>
#include <QTemporaryFile>
#include <QImageWriter>
#ifdef USE_DBUS #ifdef USE_DBUS
#include <QtDBus/QtDBus> #include <QtDBus/QtDBus>
#include <stdint.h> #include <stdint.h>
#endif #endif
#ifdef Q_WS_MAC
#include <ApplicationServices/ApplicationServices.h>
extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret);
#endif
// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128 // https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128;
@ -39,6 +46,19 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
mode = Freedesktop; mode = Freedesktop;
} }
#endif #endif
#ifdef Q_WS_MAC
// Check if Growl is installed (based on Qt's tray icon implementation)
CFURLRef cfurl;
OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
if (status != kLSApplicationNotFoundErr) {
CFBundleRef bundle = CFBundleCreate(0, cfurl);
CFRelease(cfurl);
if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
mode = Growl;
}
CFRelease(bundle);
}
#endif
} }
Notificator::~Notificator() Notificator::~Notificator()
@ -201,6 +221,54 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString &
trayIcon->showMessage(title, text, sicon, millisTimeout); trayIcon->showMessage(title, text, sicon, millisTimeout);
} }
// Based on Qt's tray icon implementation
#ifdef Q_WS_MAC
void Notificator::notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon)
{
const QString script(
"tell application \"GrowlHelperApp\"\n"
" set the allNotificationsList to {\"Notification\"}\n" // -- Make a list of all the notification types (all)
" set the enabledNotificationsList to {\"Notification\"}\n" // -- Make a list of the notifications (enabled)
" register as application \"%1\" all notifications allNotificationsList default notifications enabledNotificationsList\n" // -- Register our script with Growl
" notify with name \"Notification\" title \"%2\" description \"%3\" application name \"%1\"%4\n" // -- Send a Notification
"end tell"
);
QString notificationApp(QApplication::applicationName());
if (notificationApp.isEmpty())
notificationApp = "Application";
QPixmap notificationIconPixmap;
if (icon.isNull()) { // If no icon specified, set icon based on class
QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
switch (cls)
{
case Information: sicon = QStyle::SP_MessageBoxInformation; break;
case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
}
notificationIconPixmap = QApplication::style()->standardPixmap(sicon);
}
else {
QSize size = icon.actualSize(QSize(48, 48));
notificationIconPixmap = icon.pixmap(size);
}
QString notificationIcon;
QTemporaryFile notificationIconFile;
if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
QImageWriter writer(&notificationIconFile, "PNG");
if (writer.write(notificationIconPixmap.toImage()))
notificationIcon = QString(" image from location \"file://%1\"").arg(notificationIconFile.fileName());
}
QString quotedTitle(title), quotedText(text);
quotedTitle.replace("\\", "\\\\").replace("\"", "\\");
quotedText.replace("\\", "\\\\").replace("\"", "\\");
qt_mac_execute_apple_script(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon), 0);
}
#endif
void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{ {
switch(mode) switch(mode)
@ -213,6 +281,11 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
case QSystemTray: case QSystemTray:
notifySystray(cls, title, text, icon, millisTimeout); notifySystray(cls, title, text, icon, millisTimeout);
break; break;
#ifdef Q_WS_MAC
case Growl:
notifyGrowl(cls, title, text, icon);
break;
#endif
default: default:
if(cls == Critical) if(cls == Critical)
{ {

4
src/qt/notificator.h

@ -48,6 +48,7 @@ private:
None, None,
Freedesktop, // Use DBus org.freedesktop.Notifications Freedesktop, // Use DBus org.freedesktop.Notifications
QSystemTray, // Use QSystemTray::showMessage QSystemTray, // Use QSystemTray::showMessage
Growl // Use the Growl notification system (Mac only)
}; };
QString programName; QString programName;
Mode mode; Mode mode;
@ -58,6 +59,9 @@ private:
void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#endif #endif
void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#ifdef Q_WS_MAC
void notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon);
#endif
}; };
#endif // NOTIFICATOR_H #endif // NOTIFICATOR_H

12
src/qt/optionsdialog.cpp

@ -30,9 +30,13 @@ public:
void setMapper(MonitoredDataMapper *mapper); void setMapper(MonitoredDataMapper *mapper);
private: private:
QCheckBox *bitcoin_at_startup; QCheckBox *bitcoin_at_startup;
#ifndef Q_WS_MAC
QCheckBox *minimize_to_tray; QCheckBox *minimize_to_tray;
#endif
QCheckBox *map_port_upnp; QCheckBox *map_port_upnp;
#ifndef Q_WS_MAC
QCheckBox *minimize_on_close; QCheckBox *minimize_on_close;
#endif
QCheckBox *connect_socks4; QCheckBox *connect_socks4;
QLineEdit *proxy_ip; QLineEdit *proxy_ip;
QLineEdit *proxy_port; QLineEdit *proxy_port;
@ -167,17 +171,21 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
bitcoin_at_startup->setToolTip(tr("Automatically start Bitcoin after the computer is turned on")); bitcoin_at_startup->setToolTip(tr("Automatically start Bitcoin after the computer is turned on"));
layout->addWidget(bitcoin_at_startup); layout->addWidget(bitcoin_at_startup);
#ifndef Q_WS_MAC
minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar")); minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window")); minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
layout->addWidget(minimize_to_tray); layout->addWidget(minimize_to_tray);
#endif
map_port_upnp = new QCheckBox(tr("Map port using &UPnP")); map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.")); map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
layout->addWidget(map_port_upnp); layout->addWidget(map_port_upnp);
#ifndef Q_WS_MAC
minimize_on_close = new QCheckBox(tr("M&inimize on close")); minimize_on_close = new QCheckBox(tr("M&inimize on close"));
minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu.")); minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
layout->addWidget(minimize_on_close); layout->addWidget(minimize_on_close);
#endif
connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:")); connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)")); connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
@ -239,9 +247,13 @@ void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
{ {
// Map model to widgets // Map model to widgets
mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup); mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
#ifndef Q_WS_MAC
mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray); mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
#endif
mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP); mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
#ifndef Q_WS_MAC
mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose); mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
#endif
mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4); mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
mapper->addMapping(proxy_ip, OptionsModel::ProxyIP); mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
mapper->addMapping(proxy_port, OptionsModel::ProxyPort); mapper->addMapping(proxy_port, OptionsModel::ProxyPort);

1
src/qt/overviewpage.cpp

@ -116,6 +116,7 @@ OverviewPage::OverviewPage(QWidget *parent) :
ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE)); ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
ui->listTransactions->setSelectionMode(QAbstractItemView::NoSelection); ui->listTransactions->setSelectionMode(QAbstractItemView::NoSelection);
ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2)); ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
connect(ui->listTransactions, SIGNAL(clicked(QModelIndex)), this, SIGNAL(transactionClicked(QModelIndex))); connect(ui->listTransactions, SIGNAL(clicked(QModelIndex)), this, SIGNAL(transactionClicked(QModelIndex)));
} }

6
src/qt/sendcoinsdialog.cpp

@ -19,6 +19,12 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
#ifdef Q_WS_MAC // Icons on push buttons are very uncommon on Mac
ui->addButton->setIcon(QIcon());
ui->clearButton->setIcon(QIcon());
ui->sendButton->setIcon(QIcon());
#endif
addEntry(); addEntry();
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry())); connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));

4
src/qt/sendcoinsentry.cpp

@ -17,6 +17,10 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
#ifdef Q_WS_MAC
ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700 #if QT_VERSION >= 0x040700
ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book")); ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));

31
src/qt/transactionview.cpp

@ -38,13 +38,20 @@ TransactionView::TransactionView(QWidget *parent) :
QHBoxLayout *hlayout = new QHBoxLayout(); QHBoxLayout *hlayout = new QHBoxLayout();
hlayout->setContentsMargins(0,0,0,0); hlayout->setContentsMargins(0,0,0,0);
#ifdef Q_WS_MAC
hlayout->setSpacing(5);
hlayout->addSpacing(26);
#else
hlayout->setSpacing(0); hlayout->setSpacing(0);
hlayout->addSpacing(23); hlayout->addSpacing(23);
#endif
dateWidget = new QComboBox(this); dateWidget = new QComboBox(this);
dateWidget->setMaximumWidth(120); #ifdef Q_WS_MAC
dateWidget->setMinimumWidth(120); dateWidget->setFixedWidth(121);
#else
dateWidget->setFixedWidth(120);
#endif
dateWidget->addItem(tr("All"), All); dateWidget->addItem(tr("All"), All);
dateWidget->addItem(tr("Today"), Today); dateWidget->addItem(tr("Today"), Today);
dateWidget->addItem(tr("This week"), ThisWeek); dateWidget->addItem(tr("This week"), ThisWeek);
@ -55,8 +62,11 @@ TransactionView::TransactionView(QWidget *parent) :
hlayout->addWidget(dateWidget); hlayout->addWidget(dateWidget);
typeWidget = new QComboBox(this); typeWidget = new QComboBox(this);
typeWidget->setMaximumWidth(120); #ifdef Q_WS_MAC
typeWidget->setMinimumWidth(120); typeWidget->setFixedWidth(121);
#else
typeWidget->setFixedWidth(120);
#endif
typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES); typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) | typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
@ -79,8 +89,11 @@ TransactionView::TransactionView(QWidget *parent) :
#if QT_VERSION >= 0x040700 #if QT_VERSION >= 0x040700
amountWidget->setPlaceholderText(tr("Min amount")); amountWidget->setPlaceholderText(tr("Min amount"));
#endif #endif
amountWidget->setMaximumWidth(100); #ifdef Q_WS_MAC
amountWidget->setMinimumWidth(100); amountWidget->setFixedWidth(97);
#else
amountWidget->setFixedWidth(100);
#endif
amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this)); amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
hlayout->addWidget(amountWidget); hlayout->addWidget(amountWidget);
@ -96,7 +109,11 @@ TransactionView::TransactionView(QWidget *parent) :
vlayout->setSpacing(0); vlayout->setSpacing(0);
int width = view->verticalScrollBar()->sizeHint().width(); int width = view->verticalScrollBar()->sizeHint().width();
// Cover scroll bar width with spacing // Cover scroll bar width with spacing
#ifdef Q_WS_MAC
hlayout->addSpacing(width+2);
#else
hlayout->addSpacing(width); hlayout->addSpacing(width);
#endif
// Always show scroll bar // Always show scroll bar
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
view->setTabKeyNavigation(false); view->setTabKeyNavigation(false);

Loading…
Cancel
Save