Merge pull request #539 from laanwj/qt2
authorGavin Andresen <gavinandresen@gmail.com>
Thu, 29 Sep 2011 17:50:40 +0000 (10:50 -0700)
committerGavin Andresen <gavinandresen@gmail.com>
Thu, 29 Sep 2011 17:50:40 +0000 (10:50 -0700)
Qt GUI updates

15 files changed:
bitcoin-qt.pro
src/main.cpp
src/qt/bitcoin.cpp
src/qt/bitcoin.qrc
src/qt/bitcoingui.cpp
src/qt/forms/sendcoinsdialog.ui
src/qt/notificator.cpp
src/qt/notificator.h
src/qt/optionsdialog.cpp
src/qt/overviewpage.cpp
src/qt/sendcoinsdialog.cpp
src/qt/sendcoinsdialog.h
src/qt/transactiondesc.h
src/test/util_tests.cpp [new file with mode: 0644]
src/util.h

index b9fecb8..125b876 100644 (file)
@@ -5,19 +5,17 @@ DEFINES += QT_GUI
 # DEFINES += SSL
 CONFIG += no_include_pwd
 
+# for boost 1.37, add -mt to the boost libraries 
+# use: qmake BOOST_LIB_SUFFIX=-mt
+
+# Dependency library locations can be customized with BOOST_INCLUDE_PATH, 
+#    BOOST_LIB_PATH, BDB_INCLUDE_PATH, BDB_LIB_PATH
+#    OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively
+
 OBJECTS_DIR = build
 MOC_DIR = build
 UI_DIR = build
 
-# 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) {
@@ -26,9 +24,10 @@ count(USE_UPNP, 1) {
     LIBS += -lminiupnpc
 }
 
+# use: qmake "USE_DBUS=1"
 count(USE_DBUS, 1) {
     message(Building with DBUS (Freedesktop notifications) support)
-    DEFINES += QT_DBUS
+    DEFINES += USE_DBUS
     QT += dbus
 }
 
@@ -173,17 +172,61 @@ FORMS += \
     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
 
+isEmpty(QMAKE_LRELEASE) {
+    win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\lrelease.exe
+    else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
+}
+isEmpty(TS_DIR):TS_DIR = src/qt/locale
+# automatically build translations, so they can be included in resource file
+TSQM.name = lrelease ${QMAKE_FILE_IN}
+TSQM.input = TRANSLATIONS
+TSQM.output = $$TS_DIR/${QMAKE_FILE_BASE}.qm
+TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN}
+TSQM.CONFIG = no_link
+QMAKE_EXTRA_COMPILERS += TSQM
+bPRE_TARGETDEPS += compiler_TSQM_make_all
+
+# "Other files" to show in Qt Creator
 OTHER_FILES += \
-    README.rst
+    doc/*.rst doc/*.txt doc/README README.md
 
-# For use with MacPorts
-macx:INCLUDEPATH += /opt/local/include /opt/local/include/db48
-macx:LIBS += -L/opt/local/lib -L/opt/local/lib/db48
+# platform specific defaults, if not overridden on command line
+isEmpty(BOOST_LIB_SUFFIX) {
+    macx:BOOST_LIB_SUFFIX = -mt
+    windows:BOOST_LIB_SUFFIX = -mgw44-mt-1_43
+}
+
+isEmpty(BDB_LIB_PATH) {
+    macx:BDB_LIB_PATH = /opt/local/lib/db48
+}
 
-# Additional Mac options
+isEmpty(BDB_INCLUDE_PATH) {
+    macx:BDB_INCLUDE_PATH = /opt/local/include/db48
+}
+
+isEmpty(BOOST_LIB_PATH) {
+    macx:BOOST_LIB_PATH = /opt/local/lib
+}
+
+isEmpty(BOOST_INCLUDE_PATH) {
+    macx:BOOST_INCLUDE_PATH = /opt/local/include
+}
+
+windows:LIBS += -lws2_32 -lgdi32
+windows:DEFINES += __WXMSW__
+windows:RC_FILE = src/qt/res/bitcoin-qt.rc
+
+macx:DEFINES += __WXMAC_OSX__ MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3
 macx:ICON = src/qt/res/icons/bitcoin.icns
 macx:TARGET = "Bitcoin Qt"
+
+# Set libraries and includes at end, to use platform-defined defaults if not overridden
+INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH
+LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,)
+LIBS += -lssl -lcrypto -ldb_cxx
+LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_LIB_SUFFIX
index f129d7c..472c80a 100644 (file)
@@ -32,7 +32,6 @@ 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;
@@ -41,6 +40,8 @@ uint256 hashBestChain = 0;
 CBlockIndex* pindexBest = NULL;
 int64 nTimeBestReceived = 0;
 
+CMedianFilter<int> cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have
+
 map<uint256, CBlock*> mapOrphanBlocks;
 multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
 
@@ -65,11 +66,6 @@ int fUseUPnP = false;
 #endif
 
 
-
-
-
-
-
 //////////////////////////////////////////////////////////////////////////////
 //
 // dispatching functions
@@ -730,7 +726,7 @@ int GetTotalBlocksEstimate()
 // Return maximum amount of blocks that other nodes claim to have
 int GetNumBlocksOfPeers()
 {
-    return std::max(nMaxBlocksOfPeers, GetTotalBlocksEstimate());
+    return std::max(cPeerBlockCounts.median(), GetTotalBlocksEstimate());
 }
 
 bool IsInitialBlockDownload()
@@ -1859,10 +1855,8 @@ 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;
-        }
+
+        cPeerBlockCounts.input(pfrom->nStartingHeight);
     }
 
 
index daba512..60a9074 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char *argv[])
     // Load language file for system locale
     QString locale = QLocale::system().name();
     QTranslator translator;
-    translator.load("bitcoin_"+locale);
+    translator.load(":/translations/"+locale);
     app.installTranslator(&translator);
 
     QSplashScreen splash(QPixmap(":/images/splash"), 0);
index be0e4dc..2985bb6 100644 (file)
@@ -45,4 +45,9 @@
     <qresource prefix="/movies">
         <file alias="update_spinner">res/movies/update_spinner.mng</file>
     </qresource>
+    <qresource prefix="/translations">
+        <file alias="de_DE">locale/bitcoin_de.qm</file>
+        <file alias="nl_NL">locale/bitcoin_nl.qm</file>
+        <file alias="ru_RU">locale/bitcoin_ru.qm</file>
+    </qresource>
 </RCC>
index 3e6b547..be10b97 100644 (file)
@@ -522,11 +522,6 @@ void BitcoinGUI::gotoReceiveCoinsPage()
 void BitcoinGUI::gotoSendCoinsPage()
 {
     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);
index 5b30d99..f9dd02f 100644 (file)
@@ -25,7 +25,7 @@
         <x>0</x>
         <y>0</y>
         <width>666</width>
-        <height>162</height>
+        <height>165</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout_2">
@@ -59,7 +59,7 @@
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <property name="spacing">
-      <number>12</number>
+      <number>6</number>
      </property>
      <item>
       <widget class="QPushButton" name="addButton">
       </widget>
      </item>
      <item>
+      <widget class="QPushButton" name="clearButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Clear all</string>
+       </property>
+       <property name="icon">
+        <iconset resource="../bitcoin.qrc">
+         <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+       </property>
+       <property name="autoRepeatDelay">
+        <number>300</number>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <property name="spacing">
+        <number>3</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Balance:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="labelBalance">
+         <property name="text">
+          <string>123.456 BTC</string>
+         </property>
+         <property name="textInteractionFlags">
+          <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
index 86ccfc8..cf0c0a3 100644 (file)
@@ -9,7 +9,7 @@
 #include <QSystemTrayIcon>
 #include <QMessageBox>
 
-#ifdef QT_DBUS
+#ifdef USE_DBUS
 #include <QtDBus/QtDBus>
 #include <stdint.h>
 #endif
@@ -23,7 +23,7 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
     programName(programName),
     mode(None),
     trayIcon(trayicon)
-#ifdef QT_DBUS
+#ifdef USE_DBUS
     ,interface(0)
 #endif
 {
@@ -31,7 +31,7 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
     {
         mode = QSystemTray;
     }
-#ifdef QT_DBUS
+#ifdef USE_DBUS
     interface = new QDBusInterface("org.freedesktop.Notifications",
           "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
     if(interface->isValid())
@@ -43,12 +43,12 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
 
 Notificator::~Notificator()
 {
-#ifdef QT_DBUS
+#ifdef USE_DBUS
     delete interface;
 #endif
 }
 
-#ifdef QT_DBUS
+#ifdef USE_DBUS
 
 // Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
 class FreedesktopImage
@@ -205,7 +205,7 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
 {
     switch(mode)
     {
-#ifdef QT_DBUS
+#ifdef USE_DBUS
     case Freedesktop:
         notifyDBus(cls, title, text, icon, millisTimeout);
         break;
index 13f6a90..4217f7e 100644 (file)
@@ -6,7 +6,7 @@
 
 QT_BEGIN_NAMESPACE
 class QSystemTrayIcon;
-#ifdef QT_DBUS
+#ifdef USE_DBUS
 class QDBusInterface;
 #endif
 QT_END_NAMESPACE
@@ -52,7 +52,7 @@ private:
     QString programName;
     Mode mode;
     QSystemTrayIcon *trayIcon;
-#ifdef QT_DBUS
+#ifdef USE_DBUS
     QDBusInterface *interface;
 
     void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
index 0eeb6f8..7267e3d 100644 (file)
@@ -23,6 +23,7 @@
 /* First page of options */
 class MainOptionsPage : public QWidget
 {
+    Q_OBJECT
 public:
     explicit MainOptionsPage(QWidget *parent=0);
 
@@ -45,6 +46,7 @@ public slots:
 
 class DisplayOptionsPage : public QWidget
 {
+    Q_OBJECT
 public:
     explicit DisplayOptionsPage(QWidget *parent=0);
 
@@ -58,6 +60,8 @@ public slots:
 
 };
 
+#include "optionsdialog.moc"
+
 OptionsDialog::OptionsDialog(QWidget *parent):
     QDialog(parent), contents_widget(0), pages_widget(0),
     model(0), main_page(0), display_page(0)
index 7bade9a..f84a79f 100644 (file)
@@ -17,7 +17,7 @@
 
 class TxViewDelegate : public QAbstractItemDelegate
 {
-    //Q_OBJECT
+    Q_OBJECT
 public:
     TxViewDelegate(): QAbstractItemDelegate(), unit(BitcoinUnits::BTC)
     {
@@ -87,6 +87,7 @@ public:
     int unit;
 
 };
+#include "overviewpage.moc"
 
 OverviewPage::OverviewPage(QWidget *parent) :
     QWidget(parent),
index 852d789..58eb5c2 100644 (file)
@@ -22,6 +22,7 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
     addEntry();
 
     connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
+    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
 }
 
 void SendCoinsDialog::setModel(WalletModel *model)
@@ -36,6 +37,9 @@ void SendCoinsDialog::setModel(WalletModel *model)
             entry->setModel(model);
         }
     }
+
+    setBalance(model->getBalance(), model->getUnconfirmedBalance());
+    connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
 }
 
 SendCoinsDialog::~SendCoinsDialog()
@@ -241,3 +245,10 @@ void SendCoinsDialog::handleURL(const QUrl *url)
     }
     pasteEntry(rv);
 }
+
+void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance)
+{
+    Q_UNUSED(unconfirmedBalance);
+    int unit = model->getOptionsModel()->getDisplayUnit();
+    ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
+}
index 9c56e51..a14f99e 100644 (file)
@@ -37,6 +37,7 @@ public slots:
     void accept();
     SendCoinsEntry *addEntry();
     void updateRemoveEnabled();
+    void setBalance(qint64 balance, qint64 unconfirmedBalance);
 
 private:
     Ui::SendCoinsDialog *ui;
index 257b2cb..484bb12 100644 (file)
@@ -10,6 +10,7 @@ class CWalletTx;
 
 class TransactionDesc: public QObject
 {
+    Q_OBJECT
 public:
     // Provide human-readable extended HTML description of a transaction
     static QString toHTML(CWallet *wallet, CWalletTx &wtx);
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
new file mode 100644 (file)
index 0000000..337d901
--- /dev/null
@@ -0,0 +1,36 @@
+#include <vector>
+#include <boost/test/unit_test.hpp>
+#include <boost/foreach.hpp>
+
+#include "../util.h"
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(util_tests)
+
+BOOST_AUTO_TEST_CASE(util_MedianFilter)
+{    
+    CMedianFilter<int> filter(5, 15);
+
+    BOOST_CHECK(filter.median() == 15);
+
+    filter.input(20); // [15 20]
+    BOOST_CHECK(filter.median() == 17);
+
+    filter.input(30); // [15 20 30]
+    BOOST_CHECK(filter.median() == 20);
+
+    filter.input(3); // [3 15 20 30]
+    BOOST_CHECK(filter.median() == 17);
+
+    filter.input(7); // [3 7 15 20 30]
+    BOOST_CHECK(filter.median() == 15);
+
+    filter.input(18); // [3 7 18 20 30]
+    BOOST_CHECK(filter.median() == 18);
+
+    filter.input(0); // [0 3 7 18 30]
+    BOOST_CHECK(filter.median() == 7);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
index 33013a2..60e9943 100644 (file)
@@ -566,6 +566,51 @@ inline uint160 Hash160(const std::vector<unsigned char>& vch)
 }
 
 
+// Median filter over a stream of values
+// Returns the median of the last N numbers
+template <typename T> class CMedianFilter
+{
+private:
+    std::vector<T> vValues;
+    std::vector<T> vSorted;
+    int nSize;
+public:
+    CMedianFilter(int size, T initial_value):
+        nSize(size)
+    {
+        vValues.reserve(size);
+        vValues.push_back(initial_value);
+        vSorted = vValues;
+    }
+    
+    void input(T value)
+    {
+        if(vValues.size() == nSize)
+        {
+            vValues.erase(vValues.begin());
+        }
+        vValues.push_back(value);
+
+        vSorted.resize(vValues.size());
+        std::copy(vValues.begin(), vValues.end(), vSorted.begin());
+        std::sort(vSorted.begin(), vSorted.end());
+    }
+
+    T median() const
+    {
+        int size = vSorted.size();
+        assert(size>0);
+        if(size & 1) // Odd number of elements
+        {
+            return vSorted[size/2];
+        }
+        else // Even number of elements
+        {
+            return (vSorted[size/2-1] + vSorted[size/2]) / 2;
+        }
+    }
+};
+