Browse Source

Merge pull request #521 from laanwj/qt

Qt GUI
pull/1/head
Gavin Andresen 11 years ago
parent
commit
f7f2a36925
  1. 13
      .gitignore
  2. 1
      README.md
  3. 185
      bitcoin-qt.pro
  4. 43
      contrib/miniupnpc/Portfile
  5. 73
      doc/assets-attribution.txt
  6. 162
      doc/readme-qt.rst
  7. 63
      scripts/qt/extract_strings_qt.py
  8. BIN
      scripts/qt/img/reload.xcf
  9. 43
      scripts/qt/make_spinner.py
  10. 9
      scripts/qt/make_windows_icon.py
  11. 4
      src/bitcoinrpc.cpp
  12. 0
      src/bitcoinrpc.h
  13. 4
      src/headers.h
  14. 18
      src/init.cpp
  15. 11
      src/main.cpp
  16. 1
      src/main.h
  17. 4
      src/makefile.linux-mingw
  18. 4
      src/makefile.mingw
  19. 4
      src/makefile.osx
  20. 4
      src/makefile.unix
  21. 2
      src/makefile.vc
  22. 4
      src/noui.h
  23. 26
      src/qt/aboutdialog.cpp
  24. 27
      src/qt/aboutdialog.h
  25. 215
      src/qt/addressbookpage.cpp
  26. 59
      src/qt/addressbookpage.h
  27. 347
      src/qt/addresstablemodel.cpp
  28. 83
      src/qt/addresstablemodel.h
  29. 186
      src/qt/askpassphrasedialog.cpp
  30. 40
      src/qt/askpassphrasedialog.h
  31. 170
      src/qt/bitcoin.cpp
  32. 48
      src/qt/bitcoin.qrc
  33. 67
      src/qt/bitcoinaddressvalidator.cpp
  34. 24
      src/qt/bitcoinaddressvalidator.h
  35. 178
      src/qt/bitcoinamountfield.cpp
  36. 59
      src/qt/bitcoinamountfield.h
  37. 613
      src/qt/bitcoingui.cpp
  38. 120
      src/qt/bitcoingui.h
  39. 217
      src/qt/bitcoinstrings.cpp
  40. 181
      src/qt/bitcoinunits.cpp
  41. 57
      src/qt/bitcoinunits.h
  42. 83
      src/qt/clientmodel.cpp
  43. 60
      src/qt/clientmodel.h
  44. 83
      src/qt/csvmodelwriter.cpp
  45. 43
      src/qt/csvmodelwriter.h
  46. 115
      src/qt/editaddressdialog.cpp
  47. 47
      src/qt/editaddressdialog.h
  48. 162
      src/qt/forms/aboutdialog.ui
  49. 130
      src/qt/forms/addressbookpage.ui
  50. 148
      src/qt/forms/askpassphrasedialog.ui
  51. 105
      src/qt/forms/editaddressdialog.ui
  52. 161
      src/qt/forms/overviewpage.ui
  53. 122
      src/qt/forms/sendcoinsdialog.ui
  54. 178
      src/qt/forms/sendcoinsentry.ui
  55. 71
      src/qt/forms/transactiondescdialog.ui
  56. 23
      src/qt/guiconstants.h
  57. 74
      src/qt/guiutil.cpp
  58. 34
      src/qt/guiutil.h
  59. 1155
      src/qt/locale/bitcoin_de.ts
  60. 1441
      src/qt/locale/bitcoin_nl.ts
  61. 2173
      src/qt/locale/bitcoin_ru.ts
  62. 36
      src/qt/monitoreddatamapper.cpp
  63. 32
      src/qt/monitoreddatamapper.h
  64. 224
      src/qt/notificator.cpp
  65. 63
      src/qt/notificator.h
  66. 277
      src/qt/optionsdialog.cpp
  67. 50
      src/qt/optionsdialog.h
  68. 162
      src/qt/optionsmodel.cpp
  69. 56
      src/qt/optionsmodel.h
  70. 173
      src/qt/overviewpage.cpp
  71. 45
      src/qt/overviewpage.h
  72. 45
      src/qt/qvalidatedlineedit.cpp
  73. 28
      src/qt/qvalidatedlineedit.h
  74. 27
      src/qt/qvaluecombobox.cpp
  75. 33
      src/qt/qvaluecombobox.h
  76. 1
      src/qt/res/bitcoin-qt.rc
  77. BIN
      src/qt/res/icons/add.png
  78. BIN
      src/qt/res/icons/address-book.png
  79. BIN
      src/qt/res/icons/bitcoin.icns
  80. BIN
      src/qt/res/icons/bitcoin.ico
  81. BIN
      src/qt/res/icons/bitcoin.png
  82. BIN
      src/qt/res/icons/bitcoin_testnet.png
  83. BIN
      src/qt/res/icons/clock1.png
  84. BIN
      src/qt/res/icons/clock2.png
  85. BIN
      src/qt/res/icons/clock3.png
  86. BIN
      src/qt/res/icons/clock4.png
  87. BIN
      src/qt/res/icons/clock5.png
  88. BIN
      src/qt/res/icons/configure.png
  89. BIN
      src/qt/res/icons/connect0_16.png
  90. BIN
      src/qt/res/icons/connect1_16.png
  91. BIN
      src/qt/res/icons/connect2_16.png
  92. BIN
      src/qt/res/icons/connect3_16.png
  93. BIN
      src/qt/res/icons/connect4_16.png
  94. BIN
      src/qt/res/icons/edit.png
  95. BIN
      src/qt/res/icons/editcopy.png
  96. BIN
      src/qt/res/icons/editpaste.png
  97. BIN
      src/qt/res/icons/export.png
  98. BIN
      src/qt/res/icons/history.png
  99. BIN
      src/qt/res/icons/key.png
  100. BIN
      src/qt/res/icons/lock_closed.png
  101. Some files were not shown because too many files have changed in this diff Show More

13
.gitignore vendored

@ -9,3 +9,16 @@ src/bitcoind @@ -9,3 +9,16 @@ src/bitcoind
*.o
*.patch
.bitcoin
#compilation and Qt preprocessor part
*.o
ui_*.h
*.qm
moc_*
Makefile
bitcoin-qt
#resources cpp
qrc_*.cpp
#qt creator
*.pro.user
#mac specific
.DS_Store

1
README.md

@ -27,4 +27,3 @@ help test the Bitcoin core, please contact QA@BitcoinTesting.org. @@ -27,4 +27,3 @@ help test the Bitcoin core, please contact QA@BitcoinTesting.org.
Feature branches are created when there are major new features being
worked on by several people.

185
bitcoin-qt.pro

@ -0,0 +1,185 @@ @@ -0,0 +1,185 @@
TEMPLATE = app
TARGET =
INCLUDEPATH += src src/json src/cryptopp src/qt
DEFINES += QT_GUI
# DEFINES += SSL
CONFIG += no_include_pwd
# for boost 1.37, add -mt to the boost libraries
LIBS += -lssl -lcrypto -ldb_cxx
unix:!macx:LIBS += -lboost_system -lboost_filesystem -lboost_program_options -lboost_thread
macx:LIBS += -lboost_system-mt -lboost_filesystem-mt -lboost_program_options-mt -lboost_thread-mt
macx:DEFINES += __WXMAC_OSX__ MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3
windows:LIBS += -lboost_system-mgw44-mt-1_43 -lboost_filesystem-mgw44-mt-1_43 -lboost_program_options-mgw44-mt-1_43 -lboost_thread-mgw44-mt-1_43 -lws2_32 -lgdi32
windows:DEFINES += __WXMSW__
windows:RC_FILE = src/qt/res/bitcoin-qt.rc
# use: qmake "USE_UPNP=1"
# miniupnpc (http://miniupnp.free.fr/files/) must be installed
count(USE_UPNP, 1) {
message(Building with UPNP support)
DEFINES += USE_UPNP=$$USE_UPNP
LIBS += -lminiupnpc
}
count(USE_DBUS, 1) {
message(Building with DBUS (Freedesktop notifications) support)
DEFINES += QT_DBUS
QT += dbus
}
# for extra security against potential buffer overflows
QMAKE_CXXFLAGS += -fstack-protector
QMAKE_LFLAGS += -fstack-protector
# disable quite some warnings because bitcoin core "sins" a lot
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wno-invalid-offsetof -Wno-unused-variable -Wno-unused-parameter -Wno-sign-compare -Wno-char-subscripts -Wno-unused-value -Wno-sequence-point -Wno-parentheses -Wno-unknown-pragmas -Wno-switch
# Input
DEPENDPATH += src/qt src src/cryptopp src json/include
HEADERS += src/qt/bitcoingui.h \
src/qt/transactiontablemodel.h \
src/qt/addresstablemodel.h \
src/qt/optionsdialog.h \
src/qt/sendcoinsdialog.h \
src/qt/addressbookpage.h \
src/qt/aboutdialog.h \
src/qt/editaddressdialog.h \
src/qt/bitcoinaddressvalidator.h \
src/base58.h \
src/bignum.h \
src/util.h \
src/uint256.h \
src/serialize.h \
src/cryptopp/stdcpp.h \
src/cryptopp/smartptr.h \
src/cryptopp/simple.h \
src/cryptopp/sha.h \
src/cryptopp/secblock.h \
src/cryptopp/pch.h \
src/cryptopp/misc.h \
src/cryptopp/iterhash.h \
src/cryptopp/cryptlib.h \
src/cryptopp/cpu.h \
src/cryptopp/config.h \
src/strlcpy.h \
src/main.h \
src/net.h \
src/key.h \
src/db.h \
src/script.h \
src/noui.h \
src/init.h \
src/headers.h \
src/irc.h \
src/json/json_spirit_writer_template.h \
src/json/json_spirit_writer.h \
src/json/json_spirit_value.h \
src/json/json_spirit_utils.h \
src/json/json_spirit_stream_reader.h \
src/json/json_spirit_reader_template.h \
src/json/json_spirit_reader.h \
src/json/json_spirit_error_position.h \
src/json/json_spirit.h \
src/qt/clientmodel.h \
src/qt/guiutil.h \
src/qt/transactionrecord.h \
src/qt/guiconstants.h \
src/qt/optionsmodel.h \
src/qt/monitoreddatamapper.h \
src/qtui.h \
src/qt/transactiondesc.h \
src/qt/transactiondescdialog.h \
src/qt/bitcoinamountfield.h \
src/wallet.h \
src/keystore.h \
src/qt/transactionfilterproxy.h \
src/qt/transactionview.h \
src/qt/walletmodel.h \
src/bitcoinrpc.h \
src/qt/overviewpage.h \
src/qt/csvmodelwriter.h \
src/crypter.h \
src/qt/sendcoinsentry.h \
src/qt/qvalidatedlineedit.h \
src/qt/bitcoinunits.h \
src/qt/qvaluecombobox.h \
src/qt/askpassphrasedialog.h \
src/protocol.h \
src/qt/notificator.h
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \
src/qt/addresstablemodel.cpp \
src/qt/optionsdialog.cpp \
src/qt/sendcoinsdialog.cpp \
src/qt/addressbookpage.cpp \
src/qt/aboutdialog.cpp \
src/qt/editaddressdialog.cpp \
src/qt/bitcoinaddressvalidator.cpp \
src/cryptopp/sha.cpp \
src/cryptopp/cpu.cpp \
src/util.cpp \
src/script.cpp \
src/main.cpp \
src/init.cpp \
src/net.cpp \
src/irc.cpp \
src/db.cpp \
src/json/json_spirit_writer.cpp \
src/json/json_spirit_value.cpp \
src/json/json_spirit_reader.cpp \
src/qt/clientmodel.cpp \
src/qt/guiutil.cpp \
src/qt/transactionrecord.cpp \
src/qt/optionsmodel.cpp \
src/qt/monitoreddatamapper.cpp \
src/qt/transactiondesc.cpp \
src/qt/transactiondescdialog.cpp \
src/qt/bitcoinstrings.cpp \
src/qt/bitcoinamountfield.cpp \
src/wallet.cpp \
src/keystore.cpp \
src/qt/transactionfilterproxy.cpp \
src/qt/transactionview.cpp \
src/qt/walletmodel.cpp \
src/bitcoinrpc.cpp \
src/qt/overviewpage.cpp \
src/qt/csvmodelwriter.cpp \
src/crypter.cpp \
src/qt/sendcoinsentry.cpp \
src/qt/qvalidatedlineedit.cpp \
src/qt/bitcoinunits.cpp \
src/qt/qvaluecombobox.cpp \
src/qt/askpassphrasedialog.cpp \
src/protocol.cpp \
src/qt/notificator.cpp
RESOURCES += \
src/qt/bitcoin.qrc
FORMS += \
src/qt/forms/sendcoinsdialog.ui \
src/qt/forms/addressbookpage.ui \
src/qt/forms/aboutdialog.ui \
src/qt/forms/editaddressdialog.ui \
src/qt/forms/transactiondescdialog.ui \
src/qt/forms/overviewpage.ui \
src/qt/forms/sendcoinsentry.ui \
src/qt/forms/askpassphrasedialog.ui
CODECFORTR = UTF-8
# for lrelease/lupdate
TRANSLATIONS = src/qt/locale/bitcoin_nl.ts src/qt/locale/bitcoin_de.ts \
src/qt/locale/bitcoin_ru.ts
OTHER_FILES += \
README.rst
# For use with MacPorts
macx:INCLUDEPATH += /opt/local/include /opt/local/include/db48
macx:LIBS += -L/opt/local/lib -L/opt/local/lib/db48
# Additional Mac options
macx:ICON = src/qt/res/icons/bitcoin.icns
macx:TARGET = "Bitcoin Qt"

43
contrib/miniupnpc/Portfile

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
# $Id$
PortSystem 1.0
name miniupnpc
epoch 2
version 1.6
revision 2
categories net
platforms darwin
license BSD
maintainers singingwolfboy openmaintainer
description Lightweight client for UPnP protocol
long_description \
${description}
homepage http://miniupnp.free.fr/
master_sites http://miniupnp.free.fr/files/download.php?file=${distname}${extract.suffix}&dummy=
checksums md5 88055f2d4a061cfd4cfe25a9eae22f67 \
sha1 ef8f2edb17f2e7c5b8dc67ee80a65c199d823e0a \
rmd160 d86b75b331a3fb5525c71708548f311977c0598f
use_configure no
variant universal {}
if {[variant_isset universal]} {
set archflags ${configure.universal_cflags}
} else {
set archflags ${configure.cc_archflags}
}
build.args-append CC="${configure.cc} ${archflags}"
post-patch {
reinplace "s|-Wl,-install_name,|-Wl,-install_name,${prefix}/lib/|" ${worksrcpath}/Makefile
}
destroot.destdir PREFIX=${prefix} INSTALLPREFIX=${destroot}${prefix}
livecheck.type regex
livecheck.url http://miniupnp.free.fr/files/
livecheck.regex ${name}-(\\d+(\\.\\d{1,4})+)${extract.suffix}

73
doc/assets-attribution.txt

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
src/qt/res/src/*.svg
Designer: Wladimir van der Laan
License: Creative Commons Attribution
Icon: src/qt/res/icons/send.png
Icon Pack: Vista Style Arrow
Designer: Icons Land
License: Freeware Non-commercial
Site: http://findicons.com/icon/231371/right3green
Icon: src/qt/res/icons/address-book.png
Icon Pack: Farm-Fresh Web
Designer: FatCow Web Hosting
License: Creative Commons Attribution (by)
Site: http://findicons.com/icon/163938/book_open
Icon: src/qt/res/icons/connect*.png, src/qt/res/icons/synced.png, src/qt/res/icons/lock_*.png
Icon Pack: Human-O2
Designer: schollidesign
License: GNU/GPL
Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0
Icon: src/qt/res/icons/transaction*.png
Designer: md2k7
Site: https://forum.bitcoin.org/index.php?topic=15276.0
License: You are free to do with these icons as you wish, including selling,
copying, modifying etc.
Icon: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png,
src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png,
src/qt/res/icons/add.png, src/qt/res/icons/edit.png,
src/qt/res/icons/remove.png (edited)
Designer: http://www.everaldo.com
Icon Pack: Crystal SVG
License: LGPL
Icon: src/qt/res/icons/receive.png, src/qt/res/icons/history.png,
src/qt/res/icons/export.png
Designer: Oxygen team
Icon Pack: Oxygen
License: Creative Common Attribution-ShareAlike 3.0 License or LGPL
Site: http://www.oxygen-icons.org/
Icon: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png
Designer: Bitboy (optimized for 16x16 by Wladimir van der Laan)
License: Public Domain
Site: http://forum.bitcoin.org/?topic=1756.0
Icon: src/qt/res/icons/overview.png
Icon Pack: Primo
Designer: Jack Cai
License: Creative Commons Attribution No Derivatives (by-nd)
Site: http://findicons.com/icon/175944/home?id=176221#
Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng
Icon Pack: Kids
Designer: Everaldo (Everaldo Coelho)
License: GNU/GPL
Site: http://findicons.com/icon/17102/reload?id=17102
Image: src/qt/res/images/splash2.jpg (Wallet image)
Designer: Crobbo (forum)
Site: https://bitcointalk.org/index.php?topic=32273.0
License: Public domain
Icon: src/qt/res/icons/key.png
Designer: VisualPharm (Ivan Boyko)
Icon Pack: Must Have
Site: http://findicons.com/icon/51009/key?id=51009
License: Creative Commons Attribution (by)

162
doc/readme-qt.rst

@ -0,0 +1,162 @@ @@ -0,0 +1,162 @@
Bitcoin-qt: Qt4 based GUI replacement for Bitcoin
=================================================
Features
========
- All functionality of the Wx GUI, including wallet encryption
- Compatibility with Linux (both GNOME and KDE), MacOSX and Windows
- Notification on incoming / outgoing transactions (compatible with FreeDesktop and other desktop notification schemes)
- General interface improvements: Splash screen, tabbed interface
- Overview page with current balance, unconfirmed balance, and such
- Better transaction list with status icons, real-time filtering and a context menu
- Asks for confirmation before sending coins, for your own safety
- CSV export of transactions and address book (for Excel bookkeeping)
- Shows alternative icon when connected to testnet, so you never accidentally send real coins during testing
- Shows a progress bar on initial block download, so that you don't have to wonder how many blocks it needs to download to be up to date
- Sendmany support, send to multiple recipients at the same time
- Multiple unit support, can show subdivided bitcoins (uBTC, mBTC) for users that like large numbers
- Support for English, German, Russian and Dutch languages
- Address books and transaction table can be sorted by any column
- Accepts "bitcoin:" URLs from browsers and other sources through drag and drop
Build instructions
===================
Debian
-------
First, make sure that the required packages for Qt4 development of your
distribution are installed, for Debian and Ubuntu these are:
::
apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
libssl-dev libdb4.8++-dev
then execute the following:
::
qmake
make
Alternatively, install Qt Creator and open the `bitcoin-qt.pro` file.
An executable named `bitcoin-qt` will be built.
Windows
--------
Windows build instructions:
- Download the `QT Windows SDK`_ and install it. You don't need the Symbian stuff, just the desktop Qt.
- Download and extract the `dependencies archive`_ [#]_, or compile openssl, boost and dbcxx yourself.
- Copy the contents of the folder "deps" to "X:\\QtSDK\\mingw", replace X:\\ with the location where you installed the Qt SDK. Make sure that the contents of "deps\\include" end up in the current "include" directory.
- Open the .pro file in QT creator and build as normal (ctrl-B)
.. _`QT Windows SDK`: http://qt.nokia.com/downloads/sdk-windows-cpp
.. _`dependencies archive`: https://download.visucore.com/bitcoin/qtgui_deps_1.zip
.. [#] PGP signature: https://download.visucore.com/bitcoin/qtgui_deps_1.zip.sig (signed with RSA key ID `610945D0`_)
.. _`610945D0`: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x610945D0
Mac OS X
--------
- Download and install the `Qt Mac OS X SDK`_. It is recommended to also install Apple's Xcode with UNIX tools.
- Download and install `MacPorts`_.
- Execute the following commands in a terminal to get the dependencies:
::
sudo port selfupdate
sudo port install boost db48
- Open the .pro file in Qt Creator and build as normal (cmd-B)
.. _`Qt Mac OS X SDK`: http://qt.nokia.com/downloads/sdk-mac-os-cpp
.. _`MacPorts`: http://www.macports.org/install.php
Build configuration options
============================
UPNnP port forwarding
---------------------
To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable bitcoin experience), pass the following argument to qmake:
::
qmake "USE_UPNP=1"
(in **Qt Creator**, you can find the setting for additional qmake arguments under "Projects" -> "Build Settings" -> "Build Steps", then click "Details" next to **qmake**)
This requires miniupnpc for UPnP port mapping. It can be downloaded from
http://miniupnp.tuxfamily.org/files/. UPnP support is not compiled in by default.
Set USE_UPNP to a different value to control this:
+------------+--------------------------------------------------------------+
| USE_UPNP= | (the default) no UPnP support, miniupnpc not required; |
+------------+--------------------------------------------------------------+
| USE_UPNP=0 | UPnP support turned off by default at runtime; |
+------------+--------------------------------------------------------------+
| USE_UPNP=1 | 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.
You can execute the following commands in a terminal to install it:
::
cd <location of bitcoin-qt>/contrib/miniupnpc
sudo port install
Notification support for recent (k)ubuntu versions
---------------------------------------------------
To see desktop notifications on (k)ubuntu versions starting from 10.04, enable usage of the
FreeDesktop notification interface through DBUS using the following qmake option:
::
qmake "USE_DBUS=1"
Berkely DB version warning
==========================
A warning for people using the *static binary* version of Bitcoin on a Linux/UNIX-ish system (tl;dr: **Berkely DB databases are not forward compatible**).
The static binary version of Bitcoin is linked against libdb4.7 or libdb4.8 (see also `this Debian issue`_).
Now the nasty thing is that databases from 5.X are not compatible with 4.X.
If the globally installed development package of Berkely DB installed on your system is 5.X, any source you
build yourself will be linked against that. The first time you run with a 5.X version the database will be upgraded,
and 4.X cannot open the new format. This means that you cannot go back to the old statically linked version without
significant hassle!
.. _`this Debian issue`: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621425

63
scripts/qt/extract_strings_qt.py

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
#!/usr/bin/python
'''
Extract _("...") strings for translation and convert to Qt4 stringdefs so that
they can be picked up by Qt linguist.
'''
from subprocess import Popen, PIPE
OUT_CPP="src/qt/bitcoinstrings.cpp"
EMPTY=['""']
def parse_po(text):
"""
Parse 'po' format produced by xgettext.
Return a list of (msgid,msgstr) tuples.
"""
messages = []
msgid = []
msgstr = []
in_msgid = False
in_msgstr = False
for line in text.split('\n'):
line = line.rstrip('\r')
if line.startswith('msgid '):
if in_msgstr:
messages.append((msgid, msgstr))
in_msgstr = False
# message start
in_msgid = True
msgid = [line[6:]]
elif line.startswith('msgstr '):
in_msgid = False
in_msgstr = True
msgstr = [line[7:]]
elif line.startswith('"'):
if in_msgid:
msgid.append(line)
if in_msgstr:
msgstr.append(line)
if in_msgstr:
messages.append((msgid, msgstr))
return messages
files = ['src/base58.h', 'src/bignum.h', 'src/db.cpp', 'src/db.h', 'src/headers.h', 'src/init.cpp', 'src/init.h', 'src/irc.cpp', 'src/irc.h', 'src/key.h', 'src/main.cpp', 'src/main.h', 'src/net.cpp', 'src/net.h', 'src/noui.h', 'src/script.cpp', 'src/script.h', 'src/serialize.h', 'src/strlcpy.h', 'src/uint256.h', 'src/util.cpp', 'src/util.h']
# xgettext -n --keyword=_ $FILES
child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
(out, err) = child.communicate()
messages = parse_po(out)
f = open(OUT_CPP, 'w')
f.write('#include <QtGlobal>\n')
f.write('// Automatically generated by extract_strings.py\n')
f.write('static const char *bitcoin_strings[] = {')
for (msgid, msgstr) in messages:
if msgid != EMPTY:
f.write('QT_TRANSLATE_NOOP("bitcoin-core", %s),\n' % ('\n'.join(msgid)))
f.write('};')
f.close()

BIN
scripts/qt/img/reload.xcf

Binary file not shown.

43
scripts/qt/make_spinner.py

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
#!/usr/bin/env python
# W.J. van der Laan, 2011
# Make spinning .mng animation from a .png
# Requires imagemagick 6.7+
from __future__ import division
from os import path
from PIL import Image
from subprocess import Popen
SRC='img/reload_scaled.png'
DST='../../src/qt/res/movies/update_spinner.mng'
TMPDIR='/tmp'
TMPNAME='tmp-%03i.png'
NUMFRAMES=35
FRAMERATE=10.0
CONVERT='convert'
CLOCKWISE=True
DSIZE=(16,16)
im_src = Image.open(SRC)
if CLOCKWISE:
im_src = im_src.transpose(Image.FLIP_LEFT_RIGHT)
def frame_to_filename(frame):
return path.join(TMPDIR, TMPNAME % frame)
frame_files = []
for frame in xrange(NUMFRAMES):
rotation = (frame + 0.5) / NUMFRAMES * 360.0
if CLOCKWISE:
rotation = -rotation
im_new = im_src.rotate(rotation, Image.BICUBIC)
im_new.thumbnail(DSIZE, Image.ANTIALIAS)
outfile = frame_to_filename(frame)
im_new.save(outfile, 'png')
frame_files.append(outfile)
p = Popen([CONVERT, "-delay", str(FRAMERATE), "-dispose", "2"] + frame_files + [DST])
p.communicate()

9
scripts/qt/make_windows_icon.py

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
#!/bin/bash
# create multiresolution windows icon
ICON_SRC=../../src/qt/res/icons/bitcoin.png
ICON_DST=../../src/qt/res/icons/bitcoin.ico
convert ${ICON_SRC} -resize 16x16 bitcoin-16.png
convert ${ICON_SRC} -resize 32x32 bitcoin-32.png
convert ${ICON_SRC} -resize 48x48 bitcoin-48.png
convert bitcoin-16.png bitcoin-32.png bitcoin-48.png ${ICON_DST}

4
src/rpc.cpp → src/bitcoinrpc.cpp

@ -50,13 +50,13 @@ Object JSONRPCError(int code, const string& message) @@ -50,13 +50,13 @@ Object JSONRPCError(int code, const string& message)
}
void PrintConsole(const char* format, ...)
void PrintConsole(const std::string &format, ...)
{
char buffer[50000];
int limit = sizeof(buffer);
va_list arg_ptr;
va_start(arg_ptr, format);
int ret = _vsnprintf(buffer, limit, format, arg_ptr);
int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
va_end(arg_ptr);
if (ret < 0 || ret >= limit)
{

0
src/rpc.h → src/bitcoinrpc.h

4
src/headers.h

@ -99,8 +99,12 @@ @@ -99,8 +99,12 @@
#include "uibase.h"
#include "ui.h"
#else
#ifdef QT_GUI
#include "qtui.h"
#else
#include "noui.h"
#endif
#endif
#ifdef GUI
#include "xpm/addressbook16.xpm"

18
src/init.cpp

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#include "db.h"
#include "rpc.h"
#include "bitcoinrpc.h"
#include "net.h"
#include "init.h"
#include "strlcpy.h"
@ -80,7 +80,7 @@ void HandleSIGTERM(int) @@ -80,7 +80,7 @@ void HandleSIGTERM(int)
//
// Start
//
#ifndef GUI
#if !defined(QT_GUI) && !defined(GUI)
int main(int argc, char* argv[])
{
bool fRet = false;
@ -240,10 +240,9 @@ bool AppInit2(int argc, char* argv[]) @@ -240,10 +240,9 @@ bool AppInit2(int argc, char* argv[])
fServer = GetBoolArg("-server");
/* force fServer when running without GUI */
#ifndef GUI
#if !defined(QT_GUI) && !defined(GUI)
fServer = true;
#endif
fPrintToConsole = GetBoolArg("-printtoconsole");
fPrintToDebugger = GetBoolArg("-printtodebugger");
@ -252,6 +251,7 @@ bool AppInit2(int argc, char* argv[]) @@ -252,6 +251,7 @@ bool AppInit2(int argc, char* argv[])
fNoListen = GetBoolArg("-nolisten") || fTOR;
fLogTimestamps = GetBoolArg("-logtimestamps");
#ifndef QT_GUI
for (int i = 1; i < argc; i++)
if (!IsSwitchChar(argv[i][0]))
fCommandLine = true;
@ -261,6 +261,7 @@ bool AppInit2(int argc, char* argv[]) @@ -261,6 +261,7 @@ bool AppInit2(int argc, char* argv[])
int ret = CommandLineRPC(argc, argv);
exit(ret);
}
#endif
#ifndef __WXMSW__
if (fDaemon)
@ -373,18 +374,21 @@ bool AppInit2(int argc, char* argv[]) @@ -373,18 +374,21 @@ bool AppInit2(int argc, char* argv[])
strErrors = "";
int64 nStart;
InitMessage(_("Loading addresses..."));
printf("Loading addresses...\n");
nStart = GetTimeMillis();
if (!LoadAddresses())
strErrors += _("Error loading addr.dat \n");
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
InitMessage(_("Loading block index..."));
printf("Loading block index...\n");
nStart = GetTimeMillis();
if (!LoadBlockIndex())
strErrors += _("Error loading blkindex.dat \n");
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n");
nStart = GetTimeMillis();
bool fFirstRun;
@ -415,12 +419,14 @@ bool AppInit2(int argc, char* argv[]) @@ -415,12 +419,14 @@ bool AppInit2(int argc, char* argv[])
}
if (pindexBest != pindexRescan)
{
InitMessage(_("Rescanning..."));
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
}
InitMessage(_("Done loading"));
printf("Done loading\n");
//// debug print
@ -543,7 +549,7 @@ bool AppInit2(int argc, char* argv[]) @@ -543,7 +549,7 @@ bool AppInit2(int argc, char* argv[])
RandAddSeedPerfmon();
if (!CreateThread(StartNode, NULL))
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
if (fServer)
CreateThread(ThreadRPCServer, NULL);
@ -553,7 +559,7 @@ bool AppInit2(int argc, char* argv[]) @@ -553,7 +559,7 @@ bool AppInit2(int argc, char* argv[])
SetStartOnSystemStartup(true);
#endif
#ifndef GUI
#if !defined(QT_GUI) && !defined(GUI)
while (1)
Sleep(5000);
#endif

11
src/main.cpp

@ -32,6 +32,7 @@ uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3 @@ -32,6 +32,7 @@ uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
const int nTotalBlocksEstimate = 140700; // Conservative estimate of total nr of blocks on main chain
const int nInitialBlockThreshold = 120; // Regard blocks up until N-threshold as "initial download"
int nMaxBlocksOfPeers = 0; // Amount of blocks that other nodes claim to have
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
CBigNum bnBestChainWork = 0;
@ -726,6 +727,12 @@ int GetTotalBlocksEstimate() @@ -726,6 +727,12 @@ int GetTotalBlocksEstimate()
}
}
// Return maximum amount of blocks that other nodes claim to have
int GetNumBlocksOfPeers()
{
return std::max(nMaxBlocksOfPeers, GetTotalBlocksEstimate());
}
bool IsInitialBlockDownload()
{
if (pindexBest == NULL || nBestHeight < (GetTotalBlocksEstimate()-nInitialBlockThreshold))
@ -1840,6 +1847,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1840,6 +1847,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
if(pfrom->nStartingHeight > nMaxBlocksOfPeers)
{
nMaxBlocksOfPeers = pfrom->nStartingHeight;
}
}

1
src/main.h

@ -99,6 +99,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash @@ -99,6 +99,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
int GetTotalBlocksEstimate();
int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);

4
src/makefile.linux-mingw

@ -49,7 +49,7 @@ HEADERS = \ @@ -49,7 +49,7 @@ HEADERS = \
net.h \
noui.h \
protocol.h \
rpc.h \
bitcoinrpc.h \
script.h \
serialize.h \
strlcpy.h \
@ -76,7 +76,7 @@ OBJS= \ @@ -76,7 +76,7 @@ OBJS= \
obj/main.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/bitcoinrpc.o \
obj/script.o \
obj/util.o \
obj/wallet.o \

4
src/makefile.mingw

@ -46,7 +46,7 @@ HEADERS = \ @@ -46,7 +46,7 @@ HEADERS = \
net.h \
noui.h \
protocol.h \
rpc.h \
bitcoinrpc.h \
script.h \
serialize.h \
strlcpy.h \
@ -74,7 +74,7 @@ OBJS= \ @@ -74,7 +74,7 @@ OBJS= \
obj/main.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/bitcoinrpc.o \
obj/script.o \
obj/util.o \
obj/wallet.o \

4
src/makefile.osx vendored

@ -46,7 +46,7 @@ HEADERS = \ @@ -46,7 +46,7 @@ HEADERS = \
net.h \
noui.h \
protocol.h \
rpc.h \
bitcoinrpc.h \
script.h \
serialize.h \
strlcpy.h \
@ -65,7 +65,7 @@ OBJS= \ @@ -65,7 +65,7 @@ OBJS= \
obj/main.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/bitcoinrpc.o \
obj/script.o \
obj/util.o \
obj/wallet.o \

4
src/makefile.unix

@ -52,7 +52,7 @@ HEADERS = \ @@ -52,7 +52,7 @@ HEADERS = \
net.h \
noui.h \
protocol.h \
rpc.h \
bitcoinrpc.h \
script.h \
serialize.h \
strlcpy.h \
@ -71,7 +71,7 @@ OBJS= \ @@ -71,7 +71,7 @@ OBJS= \
obj/main.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/bitcoinrpc.o \
obj/script.o \
obj/util.o \
obj/wallet.o \

2
src/makefile.vc

@ -59,7 +59,7 @@ HEADERS = \ @@ -59,7 +59,7 @@ HEADERS = \
net.h \
noui.h \
protocol.h \
rpc.h \
bitcoinrpc.h \
script.h \
serialize.h \
strlcpy.h \

4
src/noui.h

@ -67,4 +67,8 @@ inline void MainFrameRepaint() @@ -67,4 +67,8 @@ inline void MainFrameRepaint()
{
}
inline void InitMessage(const std::string &message)
{
}
#endif

26
src/qt/aboutdialog.cpp

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
#include "aboutdialog.h"
#include "ui_aboutdialog.h"
#include "clientmodel.h"
AboutDialog::AboutDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AboutDialog)
{
ui->setupUi(this);
}
void AboutDialog::setModel(ClientModel *model)
{
ui->versionLabel->setText(model->formatFullVersion());
}
AboutDialog::~AboutDialog()
{
delete ui;
}
void AboutDialog::on_buttonBox_accepted()
{
close();
}

27
src/qt/aboutdialog.h

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H
#include <QDialog>
namespace Ui {
class AboutDialog;
}
class ClientModel;
class AboutDialog : public QDialog
{
Q_OBJECT
public:
explicit AboutDialog(QWidget *parent = 0);
~AboutDialog();
void setModel(ClientModel *model);
private:
Ui::AboutDialog *ui;
private slots:
void on_buttonBox_accepted();
};
#endif // ABOUTDIALOG_H

215
src/qt/addressbookpage.cpp

@ -0,0 +1,215 @@ @@ -0,0 +1,215 @@
#include "addressbookpage.h"
#include "ui_addressbookpage.h"
#include "addresstablemodel.h"
#include "editaddressdialog.h"
#include "csvmodelwriter.h"
#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QFileDialog>
#include <QMessageBox>
AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
QDialog(parent),
ui(new Ui::AddressBookPage),
model(0),
mode(mode),
tab(tab)
{
ui->setupUi(this);
switch(mode)
{
case ForSending:
connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableView->setFocus();
break;
case ForEditing:
ui->buttonBox->hide();
break;
}
switch(tab)
{
case SendingTab:
ui->labelExplanation->hide();
break;
case ReceivingTab:
break;
}
ui->tableView->setTabKeyNavigation(false);
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}
AddressBookPage::~AddressBookPage()
{
delete ui;
}
void AddressBookPage::setModel(AddressTableModel *model)
{
this->model = model;
// Refresh list from core
model->updateList();
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model);
proxyModel->setDynamicSortFilter(true);
switch(tab)
{
case ReceivingTab:
// Receive filter
proxyModel->setFilterRole(AddressTableModel::TypeRole);
proxyModel->setFilterFixedString(AddressTableModel::Receive);
break;
case SendingTab:
// Send filter
proxyModel->setFilterRole(AddressTableModel::TypeRole);
proxyModel->setFilterFixedString(AddressTableModel::Send);
break;
}
ui->tableView->setModel(proxyModel);
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
// Set column widths
ui->tableView->horizontalHeader()->resizeSection(
AddressTableModel::Address, 320);
ui->tableView->horizontalHeader()->setResizeMode(
AddressTableModel::Label, QHeaderView::Stretch);
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged()));
if(mode == ForSending)
{
// Auto-select first row when in sending mode
ui->tableView->selectRow(0);
}
selectionChanged();
}
QTableView *AddressBookPage::getCurrentTable()
{
return ui->tableView;
}
void AddressBookPage::on_copyToClipboard_clicked()
{
// Copy currently selected address to clipboard
// (or nothing, if nothing selected)
QTableView *table = getCurrentTable();
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
foreach (QModelIndex index, indexes)
{
QVariant address = index.data();
QApplication::clipboard()->setText(address.toString());
}
}
void AddressBookPage::on_newAddressButton_clicked()
{
EditAddressDialog dlg(
tab == SendingTab ?
EditAddressDialog::NewSendingAddress :
EditAddressDialog::NewReceivingAddress);
dlg.setModel(model);
if(dlg.exec())
{
// Select row for newly created address
QString address = dlg.getAddress();
QModelIndexList lst = proxyModel->match(proxyModel->index(0,
AddressTableModel::Address, QModelIndex()),
Qt::EditRole, address, 1, Qt::MatchExactly);
if(!lst.isEmpty())
{
ui->tableView->setFocus();
ui->tableView->selectRow(lst.at(0).row());
}
}
}
void AddressBookPage::on_deleteButton_clicked()
{
QTableView *table = getCurrentTable();
QModelIndexList indexes = table->selectionModel()->selectedRows();
if(!indexes.isEmpty())
{
table->model()->removeRow(indexes.at(0).row());
}
}
void AddressBookPage::selectionChanged()
{
// Set button states based on selected tab and selection
QTableView *table = getCurrentTable();
if(table->selectionModel()->hasSelection())
{
switch(tab)
{
case SendingTab:
ui->deleteButton->setEnabled(true);
break;
case ReceivingTab:
ui->deleteButton->setEnabled(false);
break;
}
ui->copyToClipboard->setEnabled(true);
}
else
{
ui->deleteButton->setEnabled(false);
ui->copyToClipboard->setEnabled(false);
}
}
void AddressBookPage::done(int retval)
{
// When this is a tab/widget and not a model dialog, ignore "done"
if(mode == ForEditing)
return;
// Figure out which address was selected, and return it
QTableView *table = getCurrentTable();
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
foreach (QModelIndex index, indexes)
{
QVariant address = table->model()->data(index);
returnValue = address.toString();
}
if(returnValue.isEmpty())
{
retval = Rejected;
}
QDialog::done(retval);
}
void AddressBookPage::exportClicked()
{
// CSV is currently the only supported format
QString filename = QFileDialog::getSaveFileName(
this,
tr("Export Address Book Data"),
QDir::currentPath(),
tr("Comma separated file (*.csv)"));
if (filename.isNull()) return;
CSVModelWriter writer(filename);
// name, column, role
writer.setModel(proxyModel);
writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);
if(!writer.write())
{
QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
QMessageBox::Abort, QMessageBox::Abort);
}
}

59
src/qt/addressbookpage.h

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
#ifndef ADDRESSBOOKPAGE_H
#define ADDRESSBOOKPAGE_H
#include <QDialog>
namespace Ui {
class AddressBookPage;
}
class AddressTableModel;
QT_BEGIN_NAMESPACE
class QTableView;
class QItemSelection;
class QSortFilterProxyModel;
QT_END_NAMESPACE
class AddressBookPage : public QDialog
{
Q_OBJECT
public:
enum Tabs {
SendingTab = 0,
ReceivingTab = 1
};
enum Mode {
ForSending, // Pick address for sending
ForEditing // Open address book for editing
};
explicit AddressBookPage(Mode mode, Tabs tab, QWidget *parent = 0);
~AddressBookPage();
void setModel(AddressTableModel *model);
const QString &getReturnValue() const { return returnValue; }
public slots:
void done(int retval);
void exportClicked();
private:
Ui::AddressBookPage *ui;
AddressTableModel *model;
Mode mode;
Tabs tab;
QString returnValue;
QSortFilterProxyModel *proxyModel;
QTableView *getCurrentTable();
private slots:
void on_deleteButton_clicked();
void on_newAddressButton_clicked();
void on_copyToClipboard_clicked();
void selectionChanged();
};
#endif // ADDRESSBOOKDIALOG_H

347
src/qt/addresstablemodel.cpp

@ -0,0 +1,347 @@ @@ -0,0 +1,347 @@
#include "addresstablemodel.h"
#include "guiutil.h"
#include "walletmodel.h"
#include "headers.h"
#include <QFont>
#include <QColor>
const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";
struct AddressTableEntry
{
enum Type {
Sending,
Receiving
};
Type type;
QString label;
QString address;
AddressTableEntry() {}
AddressTableEntry(Type type, const QString &label, const QString &address):
type(type), label(label), address(address) {}
};
// Private implementation
struct AddressTablePriv
{
CWallet *wallet;
QList<AddressTableEntry> cachedAddressTable;
AddressTablePriv(CWallet *wallet):
wallet(wallet) {}
void refreshAddressTable()
{
cachedAddressTable.clear();
CRITICAL_BLOCK(wallet->cs_wallet)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
const std::string& strName = item.second;
bool fMine = wallet->HaveKey(address);
cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
QString::fromStdString(strName),
QString::fromStdString(address.ToString())));
}
}
}
int size()
{
return cachedAddressTable.size();
}
AddressTableEntry *index(int idx)
{
if(idx >= 0 && idx < cachedAddressTable.size())
{
return &cachedAddressTable[idx];
}
else
{
return 0;
}
}
};
AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
{
columns << tr("Label") << tr("Address");
priv = new AddressTablePriv(wallet);
priv->refreshAddressTable();
}
AddressTableModel::~AddressTableModel()
{
delete priv;
}
int AddressTableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return priv->size();
}
int AddressTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return columns.length();
}
QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
if(role == Qt::DisplayRole || role == Qt::EditRole)
{
switch(index.column())
{
case Label:
if(rec->label.isEmpty() && role == Qt::DisplayRole)
{
return tr("(no label)");
}
else
{
return rec->label;
}
case Address:
return rec->address;
}
}
else if (role == Qt::FontRole)
{
QFont font;
if(index.column() == Address)
{
font = GUIUtil::bitcoinAddressFont();
}
return font;
}
else if (role == TypeRole)
{
switch(rec->type)
{
case AddressTableEntry::Sending:
return Send;
case AddressTableEntry::Receiving:
return Receive;
default: break;
}
}
return QVariant();
}
bool AddressTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
if(!index.isValid())
return false;
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
editStatus = OK;
if(role == Qt::EditRole)
{
switch(index.column())
{
case Label:
wallet->SetAddressBookName(rec->address.toStdString(), value.toString().toStdString());
rec->label = value.toString();
break;
case Address:
// Refuse to set invalid address, set error status and return false
if(!walletModel->validateAddress(value.toString()))
{
editStatus = INVALID_ADDRESS;
return false;
}
// Double-check that we're not overwriting a receiving address
if(rec->type == AddressTableEntry::Sending)
{
CRITICAL_BLOCK(wallet->cs_wallet)
{
// Remove old entry
wallet->DelAddressBookName(rec->address.toStdString());
// Add new entry with new address
wallet->SetAddressBookName(value.toString().toStdString(), rec->label.toStdString());
}
rec->address = value.toString();
}
break